功能要求日期选择组件只保留一个日历面板。常见的日期范围组件默认一左一右展示2个日历面板,ant-design-vue": "4.x"目前也不支持展示单日历面板,
看了文档提供的事件,感觉这事可以做,那么只能自己动手试试课。
顺便推荐一个支持单日历展示的插件。vue2-daterange-picker
常见的日期范围组件
最终效果
代码示例
1 2 3 4 5 6 7 8 9 10 11 12 13
| <div class="container"> 时间: <a-range-picker v-model:value="dateRangeValue" format="YYYY-MM-DD" :placeholder="['开始日期', '结束日期']" class="customer-date-range-picker" @change="handleDateRangeChange" @openChange="handlePickerOpenChange" allow-clear="false" /> <div> {{start}} ~ {{end}}</div> </div>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
| import { ref, nextTick } from 'vue'; import dayjs from 'dayjs';
const dateRangeValue = ref([]); const isPickerOpen = ref(false); const activePickerInput = ref('start'); const start = ref(""); const end = ref("");
const handleDateRangeChange = (dates) => { start.value = dayjs(dates[0]).format("YYYY-MM-DD"); end.value = dayjs(dates[1]).format("YYYY-MM-DD");
};
const handlePickerOpenChange = (open) => { isPickerOpen.value = open; if (open) { nextTick(() => { setupPickerPanelSwitcher(); }); } else { activePickerInput.value = 'start'; } };
const setupPickerPanelSwitcher = () => { nextTick(() => { const pickerInputs = document.querySelectorAll('.customer-date-range-picker .ant-picker-input input'); const panelContainer = document.querySelector('.ant-picker-dropdown .ant-picker-panel-container'); if (pickerInputs.length >= 2 && panelContainer) { const startInput = pickerInputs[0]; const endInput = pickerInputs[1]; if (document.activeElement === endInput) { if (shouldShowFirstPanelForEndDate()) { panelContainer.classList.remove('show-end-panel'); activePickerInput.value = 'start'; } else { panelContainer.classList.add('show-end-panel'); activePickerInput.value = 'end'; } } else { panelContainer.classList.remove('show-end-panel'); activePickerInput.value = 'start'; } const handleStartFocus = () => { panelContainer.classList.remove('show-end-panel'); activePickerInput.value = 'start'; }; const handleEndFocus = () => { if (shouldShowFirstPanelForEndDate()) { panelContainer.classList.remove('show-end-panel'); activePickerInput.value = 'start'; } else { panelContainer.classList.add('show-end-panel'); activePickerInput.value = 'end'; } }; startInput?.addEventListener('focus', handleStartFocus, { once: false }); endInput?.addEventListener('focus', handleEndFocus, { once: false }); } }); };
const shouldShowFirstPanelForEndDate = () => { if (!dateRangeValue.value || !Array.isArray(dateRangeValue.value)) { return true; } const startDate = dateRangeValue.value[0]; const endDate = dateRangeValue.value[1]; if (!startDate) { return true; } if (!endDate) { return true; } const startDateMonth = dayjs(startDate).startOf('month'); const endDateMonth = dayjs(endDate).startOf('month'); console.log(startDateMonth,endDateMonth) if (endDateMonth.isSame(startDateMonth, 'month')) { return true; } return false; };
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
| .container { width: 500px; margin: 300px auto; }
.ant-picker-dropdown { .ant-picker-panel-container { // 默认显示第一个面板,隐藏第二个 .ant-picker-panel:last-child { display: none !important; } // 调整单个日历面板的样式 .ant-picker-panel:first-child { border-right: none !important; // 确保第一个面板的翻页按钮可见 .ant-picker-header { display: flex !important; button { display: inline-block !important; visibility: visible !important; opacity: 1 !important; pointer-events: auto !important; } } } // 当结束日期输入框激活时,显示第二个面板,隐藏第一个 &.show-end-panel { .ant-picker-panel:first-child { display: none !important; } .ant-picker-panel:last-child { display: block !important; border-left: none !important; // 确保第二个面板的翻页按钮可见 .ant-picker-header { display: flex !important; button { display: inline-block !important; visibility: visible !important; opacity: 1 !important; pointer-events: auto !important; } } } } display: flex; justify-content: center; } }
|
总结
我们通过css来控制具体显示哪个面板,如果结束日期和开始日期在同一个月,那么无论聚焦哪个input都显示开始日期面板,反之显示结束日期面板即可。
哦对了,我最近开发了一个叫牛马工作器的chrome拓展插件,很好玩哦,感兴趣的话,给我的公众号回复牛马即可免费获取。
我的微信公众号: 梨的前端小屋