Vue3 Options转Composition API:v-date-picker初始值不显示问题
Vue3 + Vuetify 日期选择器响应性问题排查与解决
问题场景
Vue3(Vuetify v3.4.7)项目中,父组件采用Options API开发,子日期选择器组件采用Composition API。调用getApplication接口获取startDate后,v-date-picker关联的文本框未渲染该初始值,子组件始终接收不到更新后的startDate,因selectedDate为null显示“Empty”,怀疑是API风格差异导致响应性丢失。
原组件代码
父组件(原)
<template> <v-container> <v-row> <v-col> <datepicker label="Start Date" v-model="startDate" color="primary" ></datepicker> </v-col> </v-row> </v-container> </template> <script> import datepicker from '@/components/util/datepicker.vue'; export default { components: { datepicker }, data () { return { startDate: null, } }, mounted:function(){ this.getApplication(); }, methods: { getApplication: async function() { await this.$axios.get('/api/application') .then((response) => { this.startDate = response.data.startdate; console.log("StartDate: "+this.startDate); // 输出: StartDate: 2023-12-20T06:00:00.000Z }) .catch(error => { console.log(error); }); } }, } </script>
子组件(datepicker,原)
<template> <v-menu v-model="isMenuOpen" :close-on-content-click="false"> <template v-slot:activator="{ props }"> <v-text-field :label="label" :model-value="formattedDate" readonly v-bind="props" variant="outlined" density="comfortable" hide-details ></v-text-field> </template> <v-date-picker v-model="selectedDate" hide-actions title="" :color="color"> <template v-slot:header></template> </v-date-picker> </v-menu> </template> <script setup> import { ref, computed, watchEffect} from "vue"; const { label, color, modelValue } = defineProps([ "label", "color", "modelValue", ]); const emit = defineEmits(["update:modelValue"]); const isMenuOpen = ref(false); const selectedDate = ref(modelValue); const formattedDate = computed(() => { return selectedDate.value ? selectedDate.value.toLocaleDateString("en") : "Empty"; }); watchEffect(() => { selectedDate.value = modelValue; }); </script> <style> .v-overlay__content:has(> .v-date-picker) { min-width: auto!important; } </style>
更新后的解决方案
该方案实现了可复用的日期选择器组件,选择日期后自动关闭日历,日期以UTC格式存储,文本框显示MM/DD/YYYY格式:
父组件(更新后)
<template> <v-container> <v-row> <v-col> <datepicker label="Start Date" v-model="startDate" color="primary" ></datepicker> </v-col> </v-row> </v-container> </template> <script> import datepicker from '@/components/util/datepicker.vue'; export default { components: { datepicker }, data () { return { startDate: null, } }, mounted:function(){ this.getApplication(); }, methods: { getApplication: async function() { await this.$axios.get('/api/application') .then((response) => { this.startDate = new Date(response.data.startdate); // 转换为Date对象 console.log("StartDate: "+this.startDate); // 输出: StartDate: 2023-12-20T06:00:00.000Z }) .catch(error => { console.log(error); }); } }, } </script>
子组件(datepicker,更新后)
<template> <v-menu v-model="isMenuOpen" :close-on-content-click="false"> <template v-slot:activator="{ props }"> <v-text-field :label="label" :model-value="formattedDate" readonly v-bind="props" variant="outlined" density="comfortable" hide-details ></v-text-field> </template> <v-date-picker v-model="selectedDate" hide-header title="" :color="color"> <template v-slot:header></template> </v-date-picker> </v-menu> </template> <script setup> import { ref, computed} from "vue"; const emit = defineEmits(["update:modelValue"]); const props = defineProps([ "label", "color", "modelValue", ]); let isMenuOpen = ref(false); const formattedDate = computed(() => { return selectedDate.value ? selectedDate.value.toLocaleDateString("en") : ""; }); const selectedDate = computed({ get: () => { return props.modelValue; }, set: (val) => { emit('update:modelValue', val); isMenuOpen.value = false; }, }); </script> <style> .v-overlay__content:has(> .v-date-picker) { min-width: auto!important; } </style>
内容的提问来源于stack exchange,提问作者supremesector
相关产品推荐
相关产品推荐

