You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 01:25:05