效果如图:
代码如下子组件
<!-- eslint-disable vue/no-v-model-argument --> <template> <section class="home-page"> <van-calendar ref="calendar" v-bind="$attrs" :min-date="dateRange[0]" :max-date="dateRange[1]" v-on="$attrs" > <template #subtitle> <van-icon name="arrow-left" size="16" @click="scrollToDate(-1,'year')" /> <span @click="scrollToDate(-1,'month')">前一个月</span> <span class="tit">{{ dateInfo.title }}</span> <span @click="scrollToDate(1,'month')">后一个月</span> <van-icon name="arrow" size="16" @click="scrollToDate(1,'year')" /> </template> </van-calendar> </section> </template> <script setup> /* * @Descripttion: 日历组件功能扩展 * @Author: sunjinbo * @Date: 2023-10-20 15:06 */ import moment from 'moment' import { Toast } from 'vant' import { ref, defineProps } from 'vue' // props参数 const { date, dateRange } = defineProps({ date: { type: Date, default: () => { return new Date() } }, dateRange: { type: Array, default: () => { return [new Date(2010, 0, 1), new Date(2030, 12, 31)] } } }) // data的数据 const dateInfo = ref({ date: date, title: moment(date).format('YYYY年MM月') }) // refs实例 const calendar = ref(null) // 视图滚动到指定日期的视图 const scrollToDate = (type, dateType) => { // 生成新的时间 const transDate = moment(dateInfo.value.date).add(type, dateType) // 做时间校验 校验成功则执行下面否则return if (!((transDate > dateRange[0]) && (transDate < dateRange[1]))) { return Toast.fail('已超出最大可选范围') } // 组合新的时间成对象类型 const year = transDate.format('YYYY') const month = parseInt(transDate.format('MM')) const newDate = { date: new Date(transDate.format()), title: year + '年' + month + '月' } // 新的时间覆盖之前的时间 dateInfo.value = newDate calendar.value.scrollToDate(new Date(dateInfo.value.date)) } </script> <style lang="less" scoped> /deep/.van-calendar__header-subtitle { display: flex; align-items: center; justify-content: space-evenly; .tit { font-weight: 600; color: #1a73e8; } } </style>
父组件调用
<!-- eslint-disable vue/no-v-model-argument --> <template> <section class="home-page"> <van-cell title="选择多个日期" :value="text" @click="show = true" /> <comp-calendar v-model:show="show" type="range" @confirm="onConfirm" /></section> </template> <script setup> import CompCalendar from '@components/Calendar.vue' import { ref } from 'vue' const show = ref(false) const text = ref(null) const formatDate = (date) => `${date.getMonth() + 1}/${date.getDate()}` const onConfirm = (values) => { const [start, end] = values show.value = false text.value = `${formatDate(start)} - ${formatDate(end)}` } </script> <style lang="less" scoped> </style>
参考vue2其他博客封装 vue2封装连接Vant组件库封装可翻页日历组件_vant日历-优快云博客