封装vuetify3中v-time-picker组件,并解决使用时分秒类型只能在修改秒之后v-model才会同步更新的问题

目前时间组件还属于实验室组件,要使用需要单独引入,具体使用方式查看官网

创建公共时间选择器组件

common-time-pickers.vue 子组件页面

复制代码
<template>
  <div>
    <v-dialog v-model="props.timeItem.isShow" activator="parent" width="auto">
      <v-time-picker
        v-if="props.timeItem.isShow"
        v-model="timeVal"
        use-seconds
        format="24hr"
        color="primary"
        class="pa-0"
        @update:hour="updateHour"
        @update:minute="updateMinute"
        @update:second="updateSecond"
      >
        <template v-slot:title>
          <!-- title null -->
        </template>
        <template v-slot:actions>
          <div class="mt-6">
            <v-btn @click="emit('close')">取消</v-btn>
            <v-btn color="primary" @click="saveTime">确认</v-btn>
          </div>
        </template>
      </v-time-picker>
    </v-dialog>
  </div>
</template>

<script setup>
const props = defineProps({
  timeItem: {
    type: Object,
    default: () => {
      return {
        isShow: false,
        time: "00:00:00",
        index: 0, //操作索引,可不传
        type: "", //操作类型
      };
    },
  },
});

const emit = defineEmits(["update:timeItem", "close"]);

const timeVal = ref(props.timeItem.time);

const hours = ref(0);
const minutes = ref(0);
const seconds = ref(0);

watch(
  toRef(props, "timeItem"),
  (newVal) => {
    if (newVal.isShow) {
      timeVal.value = newVal.time;
      // const [h, m, s] = newVal.time.split(':');
      // hours.value = parseInt(h, 10);
      // minutes.value = parseInt(m, 10);
      // seconds.value = parseInt(s, 10);
      // updateTimeVal();
    }
  },
  { deep: true }
);

// 因为组件中使用了use-second,默认只有在"秒"发生改变时,v-model中的值才会更新,
// 所以需要额外绑定"时"、"分"、"秒" 的事件进行处理
const updateHour = (val) => {
  hours.value = val;
  updateTimeVal("hour");
};

const updateMinute = (val) => {
  minutes.value = val;
  updateTimeVal("minute");
};

const updateSecond = (val) => {
  seconds.value = val;
  updateTimeVal("second");
};

const updateTimeVal = (updatedPart) => {
  let [currentHours, currentMinutes, currentSeconds] = timeVal.value.split(":");

  // 确保每次更新时不改变其他值,否则修改"时"或其他值时,可能会导致"分"和"秒"被联动更改
  if (updatedPart === "hour") {
    currentHours = padZero(hours.value);
  } else if (updatedPart === "minute") {
    currentMinutes = padZero(minutes.value);
  } else if (updatedPart === "second") {
    currentSeconds = padZero(seconds.value);
  }

  timeVal.value = `${currentHours}:${currentMinutes}:${currentSeconds}`;
  // console.log("更新了++++", timeVal.value);
};

const padZero = (num) => {
  return num < 10 ? "0" + num : num.toString();
};

const saveTime = () => {
  emit("close");
  emit("update:timeItem", {
    time: timeVal.value,
    index: props.timeItem.index,
    type: props.timeItem.type,
  });
};
</script>

<style lang="scss" scoped></style>

页面效果

我这里修改的是表格中的开始时间和结束时间,属于数组中值需要遍历,如果你只需要设置单个值,可不传索引

父组件中使用

vue中

复制代码
<template>
  <div>
  <!--输入框调用子组件,可以有多个输入框,这里只演示一个,item.endTime是输入框同步的时间,也会更新到子组件中,index是操作的对象索引,如果不传递需要对selecteTime方法稍作修改,endTime是修改的对象键值,方便拿到返回值时更新父组件的值-->
  <v-text-field
        v-model="item.endTime"
        readonly
         hide-details
         density="compact"
         @click="selecteTime(item.endTime, index, 'endTime')"
      >
   </v-text-field>
   
     <!--引入组件-->
    <common-time-pickers
      :timeItem="timeItem"
      @close="timeItem.isShow = false"
      @update:timeItem="updateTimeItem"
    />
     </div>
</template>

script中

复制代码
 import commonTimePickers from "@/components/common-time-pickers.vue"
 
<script setup>
const timeItem = ref({});

// 输入框触发,选择时间
const selecteTime = (time, index, type) => {
  timeItem.value = {
    isShow: true,//打开弹框
    time,//时间,需要同步更新到子组件中
    index,//修改的对象索引(非必须)
    type,//修改的对象字段类型
  };
};

//确认更新时间
const updateTimeItem = (payload) => {
  timeItem.value.isShow = false;
  const { time, index, type } = payload;
  // console.log("确定时间>>>", payload);
  // 使用展开运算符和计算属性名更新对象
  // 更新desserts数组中索引为index的type字段值(已经可以收到时间子组件传递过来的最新的值了,根据自己的需求更改父组件中值)
  desserts.value[index] = { ...desserts.value[index], [type]: time };
};


</script>
相关推荐
卸任11 小时前
Vibe coding工具使用心得
前端·ai编程
brien912 小时前
为什么模型标称 1M,Google Antigravity 聊到 256K 却突然失忆?我们给它做了个原生行内监控圆环
前端
修炼的dance12 小时前
录屏关键帧间隔多少合适?六档实测,2秒到10秒小了75.6%
前端
Lank_M12 小时前
关键帧从1秒拉到10秒,录屏小87.3%,摄像头小10.8%
前端
补码缩写12 小时前
用 ffprobe 拆录屏,八成字节在 29 个关键帧上
前端
百思不得小李12 小时前
一个复杂的动态表单是如何实现的
前端·设计模式
陈随易12 小时前
Cmder 停更 17 个月,2.0 支持 Windows Terminal
前端·后端·程序员
清晨Coding12 小时前
删了 Cookie 还能自动登录?Google系网站登录态自动恢复的原理分析
javascript
风骏时光牛马12 小时前
前沿视界
前端
kyriewen12 小时前
我扫了 814 个依赖,97 个还敢要 Node 10
前端·javascript·程序员