Vuetify2 VDatePicker年份选择器打开位置异常修复咨询
问题解决:Vuetify2 VDatePicker年份视图打开时自动滚动到末尾的问题
问题场景
在Vue2+Vuetify2项目中使用VDatePicker组件,设置active-picker为YEAR,年份范围限定在2000到2100之间。打开组件时,偶尔会自动滚动到末尾年份(如2100、2099),而非停留在当前年份。尝试设置value为new Date()后问题仍存在。
解决方案
核心问题分析
出现该问题的原因主要有两点:
VDatePicker同时绑定了v-model="date"和:value="defaultValue",导致值绑定冲突,组件无法正确识别应该定位的年份。- 菜单打开时仅切换了
active-picker,但未确保date有有效值,当date为空时,组件会默认滚动到年份范围的末尾。
具体修复步骤
- 移除重复的value绑定:删除
VDatePicker上的:value="defaultValue"属性,仅保留v-model="date"。 - 菜单打开时初始化日期:在菜单打开的监听逻辑中,若
date为空,将其设置为当前日期的ISO格式字符串,确保年份选择器能定位到当前年份。 - 修正日期格式化方法:
getFormattedTime方法需返回可读的日期字符串,而非直接返回Date对象。
修改后的代码
组件模板
<v-menu v-model="menu" :close-on-content-click="false" offset-y transition="scale-transition" min-width="290" > <template v-slot:activator="{ on, attrs }"> <div v-if="$slots.activator" v-bind="attrs" v-on="on"> <slot name="activator"></slot> </div> <v-card v-else flat width="100%"> <v-text-field :disabled="disabled" :outlined="outlined" :dense="dense" :filled="filled" :rules="[...rules]" v-bind="attrs" v-on="on" :value="getFormattedTime(date)" :hide-details="hideDetails" :label="label" placeholder="选择日期" :error-messages="errorMessages" prepend-inner-icon="mdi-calendar" clearable @click:clear="clearDate()" readonly > <template v-slot:append> <v-icon class="pr-2"> mdi-menu-down </v-icon> </template> </v-text-field> </v-card> </template> <v-card width="290"> <v-card-text class="pa-0"> <v-date-picker v-model="date" color="primary" no-title :disabled="disabled" :min="min" @click:date="changeData" :max="max" :active-picker.sync="activePicker" first-day-of-week="1" :readonly="readonly" ></v-date-picker> </v-card-text> </v-card> </v-menu>
脚本代码
props: { value: { required: false, type: String }, label: { required: false, default: "", type: String }, min: { required: false, default: new Date("2000-01-01").toISOString(), type: String }, max: { required: false, default: new Date("2100-01-01").toISOString(), type: String }, hideDetails: { required: false, default: false, type: Boolean }, disabled: { required: false, default: false, type: Boolean }, outlined: { required: false, default: false, type: Boolean }, dense: { required: false, default: false, type: Boolean }, filled: { required: false, default: false, type: Boolean }, errorMessages: { required: false, default: null, type: [String, Number, Array, Boolean] }, rules: { required: false, default: () => [], type: Array }, yearSelect: { required: false, default: true, type: Boolean }, readonly: { required: false, default: false, type: Boolean } }, data: () => ({ activePicker: null, date: "", menu: false }), watch: { value: { immediate: true, handler() { this.date = this.value || ""; } }, menu(val) { if (val) { this.$nextTick(() => { // 若date为空,设置为当前日期 if (!this.date) { this.date = new Date().toISOString().split('T')[0]; } this.activePicker = 'YEAR'; }); } } }, methods: { changeData() { this.$emit("input", this.date); this.menu = false; }, close() { this.date = ""; this.changeData(); this.menu = false; }, toggle() { this.menu = !this.menu; }, clearDate() { this.date = ""; this.changeData(); }, getFormattedTime(date) { if (!date) return ""; const newDate = new Date(date); // 格式化日期为YYYY-MM-DD,可根据需求调整格式 return `${newDate.getFullYear()}-${String(newDate.getMonth()+1).padStart(2, '0')}-${String(newDate.getDate()).padStart(2, '0')}`; } }
说明
修改后,每次打开日期选择器时:
- 若已有选中日期,年份视图会定位到该日期的年份;
- 若无选中日期,会自动设置当前日期并定位到当前年份,不会再滚动到范围末尾。
内容的提问来源于stack exchange,提问作者WhyMe7
相关产品推荐
相关产品推荐

