Vue3动态倒计时的代码实现
作者:码农研究僧
在使用Vue框架开发Web应用时,倒计时功能是一个常见的需求,它可以在一定时间内重复执行某些操作,比如防止用户重复提交表单、限制投票次数、实现验证码获取等功能,所以本文给大家介绍了Vue3动态倒计时的代码实现,需要的朋友可以参考下
1. Demo
给一版初始的Demo,在给一版实战中的Demo
基本知识点:
- Vue 3 的响应式原理:Vue 3 使用 reactive 和 ref 创建响应式数据,数据的变化会自动触发视图更新
- setup 函数:Vue 3 引入了 Composition API,其中的 setup 函数是组件逻辑的入口
- watch 侦听器:用于侦听响应式数据的变化,在倒计时场景中可以用于监听时间的变化
- 生命周期钩子:如 onMounted 和 onUnmounted 用于在组件挂载和销毁时启动和清理倒计时
- setInterval 和 clearInterval:用于每隔一段时间执行倒计时任务
Demo:
<template> <div> <table> <thead> <tr> <th>任务名称</th> <th>剩余时间</th> </tr> </thead> <tbody> <tr v-for="task in tasks" :key="task.id"> <td>{{ task.name }}</td> <td>{{ task.remainingTime }} 秒</td> </tr> </tbody> </table> </div> </template> <script setup> import { reactive, onMounted, onUnmounted } from 'vue'; const tasks = reactive([ { id: 1, name: '任务A', remainingTime: 60 }, { id: 2, name: '任务B', remainingTime: 120 }, { id: 3, name: '任务C', remainingTime: 180 }, ]); let intervalId; onMounted(() => { intervalId = setInterval(() => { tasks.forEach(task => { if (task.remainingTime > 0) { task.remainingTime -= 1; } }); }, 1000); }); onUnmounted(() => { clearInterval(intervalId); }); </script>
2. 实战Demo
本身倒计时的某一列时间是固定的,那就不需要通过后端来获取动态数据,只需要基于appointmentEndTime和当前时间来计算倒计时。对于超过当前时间的数据,可以直接显示“已结束”或其他提示
以下是基于Vue 3的倒计时实现方式,重点是如何根据appointmentEndTime与当前时间来动态更新表格的倒计时列
- appointmentEndTime 固定:你可以直接在表格数据中使用固定的时间戳。
- 倒计时逻辑:通过setInterval每秒更新一次倒计时,但如果appointmentEndTime已经过期,就不再更新。
- 无须请求后端:无需额外API请求,直接使用appointmentEndTime进行计算
<template> <div> <el-table :data="tableData" style="width: 100%"> <!-- 审核时间列 --> <el-table-column label="审核时间" align="center" prop="appointmentReviewTime" :formatter="dateFormatter" width="170px" /> <!-- 还柜时间列 --> <el-table-column label="还柜时间" align="center" prop="appointmentEndTime" :formatter="dateFormatter" width="170px" /> <!-- 倒计时列 --> <el-table-column label="倒计时" align="center" width="170px"> <template #default="scope"> <span>{{ formatCountdown(scope.row.appointmentEndTime) }}</span> </template> </el-table-column> </el-table> </div> </template> <script> import { ref, onMounted, onBeforeUnmount } from 'vue'; export default { setup() { // 表格数据,appointmentEndTime 是固定的时间 const tableData = ref([ { appointmentReviewTime: '2024-09-20 12:00:00', appointmentEndTime: '2024-09-20 14:00:00' // 固定时间 }, { appointmentReviewTime: '2024-09-21 15:00:00', appointmentEndTime: '2024-09-21 17:00:00' // 固定时间 } ]); // 倒计时格式化函数 const formatCountdown = (endTime) => { const now = new Date().getTime(); const endTimestamp = new Date(endTime).getTime(); const remainingTime = endTimestamp - now; // 如果已过期,返回 "已结束" if (remainingTime <= 0) { return '已结束'; } const hours = Math.floor(remainingTime / (1000 * 60 * 60)); const minutes = Math.floor((remainingTime % (1000 * 60 * 60)) / (1000 * 60)); const seconds = Math.floor((remainingTime % (1000 * 60)) / 1000); return `${hours}小时 ${minutes}分钟 ${seconds}秒`; }; // 使用 setInterval 动态更新倒计时 const intervalId = ref(null); onMounted(() => { intervalId.value = setInterval(() => { // 强制触发视图更新 tableData.value = [...tableData.value]; }, 1000); }); // 清除计时器 onBeforeUnmount(() => { clearInterval(intervalId.value); }); return { tableData, formatCountdown }; } }; </script>
如果不会出现自动更新视图的,需要排查下浏览器的终端是否会有输出异常
实战中的Bug:(错误信息 queryParams.value is not iterable 表示在某处尝试遍历或解构了queryParams,但是它不是可迭代的对象,确保queryParams是一个对象或数组,不能将非迭代对象进行迭代操作)
3. 拓展Demo
appointmentEndTime这个是timestamp时间,也就是设定的未来时间
但是我要已过期,或者超过当前时间的 都显示 重新预约
那么只需要在超过当前时间或已过期的情况下显示“重新预约”
- 修改 formatCountdown 函数:
在 formatCountdown 函数中添加一个返回值,用于标记该时间是否已经过期
const formatCountdown = (endTime) => { const now = new Date().getTime(); const endTimestamp = new Date(endTime).getTime(); const remainingTime = endTimestamp - now; // 如果已过期,返回 "已过期" 并标记为需要重新预约 if (remainingTime <= 0) { return { text: '已过期', isExpired: true }; } const hours = Math.floor(remainingTime / (1000 * 60 * 60)); const minutes = Math.floor((remainingTime % (1000 * 60 * 60)) / (1000 * 60)); const seconds = Math.floor((remainingTime % (1000 * 60)) / 1000); // 分时秒的格式化 return { text: `${hours}小时 ${minutes}分钟 ${seconds}秒`, isExpired: false }; };
- 修改模板逻辑:
使用 formatCountdown 函数的返回值来判断是否显示 “重新预约”
<el-table-column label="还柜剩余时间" align="center" width="155px"> <template #default="scope"> <span>{{ formatCountdown(scope.row.appointmentEndTime).text }}</span> </template> </el-table-column> <el-button link type="primary" @click="showRejectionReason(scope.row.id)" v-if="scope.row.appointmentEndTime !== null && formatCountdown(scope.row.appointmentEndTime).isExpired" v-hasPermi="['dangerous:appointment-commission:query']" > 重新预约 </el-button>
为了在等于当前时间点的时候触发后端请求
可以修改倒计时的函数如下:
// 倒计时格式化函数 const formatCountdown = (endTime,id) => { const now = new Date().getTime(); const endTimestamp = new Date(endTime).getTime(); const remainingTime = endTimestamp - now; // 设置一个容忍时间范围(例如,1秒) const tolerance = 1000; // 1秒 // 当时间接近到达时,发送请求到后端更新状态 if (remainingTime <= tolerance && remainingTime > 0) { console.log(1); // 确保能够输出 } // 如果已过期,返回 "已过期" 并标记为需要重新预约 if (remainingTime < 0) { return { text: '已过期', isExpired: true }; } const hours = Math.floor(remainingTime / (1000 * 60 * 60)); const minutes = Math.floor((remainingTime % (1000 * 60 * 60)) / (1000 * 60)); const seconds = Math.floor((remainingTime % (1000 * 60)) / 1000); // 分时秒的格式化 return { text: `${hours}小时 ${minutes}分钟 ${seconds}秒`, isExpired: false }; };
以上的函数需要注意的点如下:
由于时间的精确性和计算方式,remainingTime 很少会正好等于 0。即使时间点非常接近,由于毫秒级的差异,可能导致 remainingTime 不完全等于 0
以上就是Vue3动态倒计时的代码实现的详细内容,更多关于Vue3动态倒计时的资料请关注脚本之家其它相关文章!