您现在的位置是:网站首页> 编程资料编程资料
vue可ctrl,shift多选,可添加标记日历组件详细_vue.js_
2023-05-24
672人已围观
简介 vue可ctrl,shift多选,可添加标记日历组件详细_vue.js_

需要写一个日历组件有以下功能,element无法满足,自己造一个
只显示当前月日期,前后月日期不显示也不可选择;周六、周日颜色与工作日区分日期可以打标记(左上角标记)可ctrl+shift+鼠标左键多选
一、 按照 "日", "一", "二", "三", "四", "五", "六" 把一个月的日期排列
页面:
{{currentMonth}}月
{{day}} {{cell.text==0?'':cell.text}}
组件定义props、emits
const props = defineProps({ markList: {//标记 type: Array, default: (): any[] => { return []; }, }, month: { type: Date, required: true, }, disabled: { type: Boolean, default: false, }, disableBefore: {//禁用今天之前的日期 type: Boolean, default: true, }, }); const emits = defineEmits(['change']); 当前月的日期数组:
type CalendarDateCellType = 'next' | 'prev' | 'current' type CalendarDateCell = { text: number, type: CalendarDateCellType } const WEEK_DAYS = ref(["日", "一", "二", "三", "四", "五", "六"]); const currentMonth = computed(() => { return moment(props.month).format('M'); }) onMounted(() => { onKeyEvent(); }) const rows = computed(() => { let days: CalendarDateCell[] = [] const firstDay = moment(props.month).startOf("month").date(); // const endDay = moment(props.month).endOf('month').date();//当前月的最后一天 const firstDayOfWeek = moment(props.month).startOf("month").day(); // const daysInMonth = moment(props.month).daysInMonth();//当前月的天数 const prevMonthDays: CalendarDateCell[] = getPrevMonthLastDays( firstDay, firstDayOfWeek - firstDay ).map((day) => ({ text: 0,//上月补0 type: 'prev', })) const currentMonthDays: CalendarDateCell[] = getMonthDays(moment(props.month).daysInMonth()).map( (day) => ({ text: day, type: 'current', }) ) days = [...prevMonthDays, ...currentMonthDays] const remaining = 7 - (days.length % 7 || 7) const nextMonthDays: CalendarDateCell[] = rangeArr(remaining).map( (_, index) => ({ text: 0,//下月补0 type: 'next', }) ) days = days.concat(nextMonthDays) // console.log(currentMonth.value, firstDay, endDay, moment(props.month).startOf("month").day()); return toNestedArr(days) })二、单元格样式处理
- 禁用
- 选中
- 周六、周日红色字体
const getCellClass = (cell: CalendarDateCell, key: number) => { let date = getCellDate(cell); if (props.disableBefore && date.getTime() < new Date().getTime()) { return ['cell', 'cell_disabled'];//禁用 } let classes: string[] = ['cell', 'cell_enabled']; if (key == 0 || key == 6) {//周六、周日 classes.push('cell_red'); } let index = selectList.value.indexOf(moment(date).format('YYYY-MM-DD')); if (index != -1) { classes.push('cell_active');//选中 } return classes; }左上角三角形标记
.triangle { position: absolute; left: 0; top: 0; width: 0; height: 0; // border-top: 30px solid #e6e911; border-right: 30px solid transparent; }const getCelltriangleStyle = (cell: CalendarDateCell) => { let date = getCellDate(cell); let day = props.markList.find(item => item.date == moment(date).format('YYYY-MM-DD')); return day ? { borderTop: '30px solid #e6e911', } : {}; }三、单机、按住ctrl点击、按住shift点击事件处理
1.记录键盘按下ctrl、shift事件
const isCtrl = ref(false) const isShift = ref(false) const onKeyEvent = () => { window.addEventListener('keydown', e => { e.preventDefault();//取消默认事件 let e1 = e || window.event switch (e1.keyCode) { case 16: isShift.value = true; break; case 17: isCtrl.value = true; break; } }) window.addEventListener('keyup', e => { e.preventDefault(); let e1 = e || window.event switch (e1.keyCode) { case 16: isShift.value = false; break; case 17: isCtrl.value = false; break; } }) }2.点击事件处理
const selectList = ref([]);//已选择的 const shiftNum = ref(0);//shift复制的起始位置 const lastSelect = ref ([]);//按住shift倒数第二次复制的 //遵循excel点击、ctrl、shift组合操作规范 const handlePickDay = (cell: CalendarDateCell) => { let date = getCellDate(cell); if (cell.type != 'current') { return; } if (props.disableBefore && date.getTime() < new Date().getTime()) { return } // console.log(isCtrl.value, isShift.value); let dateStr = moment(date).format('YYYY-MM-DD'); let currentSelect: string[] = []; //按住ctrl if (isCtrl.value) { if (selectList.value.includes(dateStr)) { selectList.value.splice(selectList.value.indexOf(dateStr), 1); } else { selectList.value.push(dateStr); } lastSelect.value = []; } else if (isShift.value) {//按住shift if (shiftNum.value == 0) {//无上次点击 shiftNum.value = cell.text; if (selectList.value.includes(dateStr)) { selectList.value.splice(selectList.value.indexOf(dateStr), 1); } else { selectList.value.push(dateStr); } } else { if (shiftNum.value < cell.text) { currentSelect = getDatesInRange(shiftNum.value, cell.text); } else if (shiftNum.value > cell.text) { currentSelect = getDatesInRange(cell.text, shiftNum.value); } else { currentSelect = [dateStr]; } selectList.value = selectList.value.filter(item => !lastSelect.value.includes(item));//移除上次按shift复制的 selectList.value = selectList.value.concat(currentSelect);//添加本次按shift复制的 lastSelect.value = currentSelect; } } else { selectList.value = [dateStr]; } if (!isShift.value) { shiftNum.value = cell.text; } selectList.value = [...new Set(selectList.value)].sort();//去重、排序 console.log(shiftNum.value, selectList.value); emits('change', selectList.value); }
3.遵循excel点击的操作方式:
- 未按ctrl、shift点击=>只选择当前点击的;
- 按ctrl点击=>未选中则选中,已选中则取消选中;
- 按住shift点击=>记录shift按下时点击位置-->再次点击时把期间内的选中,并移除倒数第二次的选中(否则都会选中,并在按下ctrl时释放上次选中)
四、组件代码:
{{currentMonth}}月
{{day}} {{cell.text==0?'':cell.text}}