封装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>
相关推荐
sunshine64124 分钟前
【CSS】实现tag选中对钩样式
前端·css·css3
真滴book理喻1 小时前
Vue(四)
前端·javascript·vue.js
蜜獾云1 小时前
npm淘宝镜像
前端·npm·node.js
dz88i81 小时前
修改npm镜像源
前端·npm·node.js
Jiaberrr1 小时前
解锁 GitBook 的奥秘:从入门到精通之旅
前端·gitbook
程序员_三木1 小时前
Three.js入门-Raycaster鼠标拾取详解与应用
开发语言·javascript·计算机外设·webgl·three.js
顾平安2 小时前
Promise/A+ 规范 - 中文版本
前端
聚名网2 小时前
域名和服务器是什么?域名和服务器是什么关系?
服务器·前端
桃园码工2 小时前
4-Gin HTML 模板渲染 --[Gin 框架入门精讲与实战案例]
前端·html·gin·模板渲染
不是鱼2 小时前
构建React基础及理解与Vue的区别
前端·vue.js·react.js