当前位置: 首页 > news >正文

动态倒计时在 Vue 3 中的实现

目录

  • 1. Demo
  • 2. 实战Demo
  • 3. 拓展Demo

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-columnlabel="审核时间"align="center"prop="appointmentReviewTime":formatter="dateFormatter"width="170px"/><!-- 还柜时间列 --><el-table-columnlabel="还柜时间"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时间,也就是设定的未来时间
但是我要已过期,或者超过当前时间的 都显示 重新预约

那么只需要在超过当前时间或已过期的情况下显示“重新预约”

  1. 修改 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 };
};
  1. 修改模板逻辑

使用 formatCountdown 函数的返回值来判断是否显示 “重新预约”

<el-table-column label="还柜剩余时间" align="center" width="155px"><template #default="scope"><span>{{ formatCountdown(scope.row.appointmentEndTime).text }}</span></template>
</el-table-column><el-buttonlinktype="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


http://www.mrgr.cn/news/34835.html

相关文章:

  • 关系型数据库 - MySQL II
  • 振弦式渗压计智慧水利工程 适用恶劣环境有保障
  • 解密云WAF的核心功能!为企业保驾护航的关键技术
  • Warrior Pack Super Bundle 人物战斗动画捆绑包
  • 等位基因与碱基:异同点解析
  • Golang plugin包教程:创建与管理插
  • 重入锁ReentrantLock详解
  • axios提交数据后台php用post方式无法正确接收
  • Oracle AI理论与实践,企业落地篇干货满满
  • 使用Python实现深度学习模型:智能电影制作与剪辑
  • FastAPI 第二课 -- 安装
  • 请不要自己写,Spring Boot非常实用的内置功能
  • 测试文件只能
  • python爬虫初体验(二)
  • 9.23作业
  • 网络工程/售后类面试题
  • CentOS一键安装Mosquitto开源消息代理结合内网穿透实现远程连接
  • 浅谈C++之多线程实现
  • 软考高级:企业信息化-数据挖掘中的上卷和下钻、旋转分析
  • tortoies-orm 一对一、一对多和多对多关系实现