Vue3動(dòng)態(tài)倒計(jì)時(shí)的代碼實(shí)現(xiàn)
1. Demo
給一版初始的Demo,在給一版實(shí)戰(zhàn)中的Demo
基本知識(shí)點(diǎn):
- Vue 3 的響應(yīng)式原理:Vue 3 使用 reactive 和 ref 創(chuàng)建響應(yīng)式數(shù)據(jù),數(shù)據(jù)的變化會(huì)自動(dòng)觸發(fā)視圖更新
- setup 函數(shù):Vue 3 引入了 Composition API,其中的 setup 函數(shù)是組件邏輯的入口
- watch 偵聽(tīng)器:用于偵聽(tīng)響應(yīng)式數(shù)據(jù)的變化,在倒計(jì)時(shí)場(chǎng)景中可以用于監(jiān)聽(tīng)時(shí)間的變化
- 生命周期鉤子:如 onMounted 和 onUnmounted 用于在組件掛載和銷(xiāo)毀時(shí)啟動(dòng)和清理倒計(jì)時(shí)
- setInterval 和 clearInterval:用于每隔一段時(shí)間執(zhí)行倒計(jì)時(shí)任務(wù)
Demo:
<template> <div> <table> <thead> <tr> <th>任務(wù)名稱(chēng)</th> <th>剩余時(shí)間</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: '任務(wù)A', remainingTime: 60 }, { id: 2, name: '任務(wù)B', remainingTime: 120 }, { id: 3, name: '任務(wù)C', remainingTime: 180 }, ]); let intervalId; onMounted(() => { intervalId = setInterval(() => { tasks.forEach(task => { if (task.remainingTime > 0) { task.remainingTime -= 1; } }); }, 1000); }); onUnmounted(() => { clearInterval(intervalId); }); </script>
2. 實(shí)戰(zhàn)Demo
本身倒計(jì)時(shí)的某一列時(shí)間是固定的,那就不需要通過(guò)后端來(lái)獲取動(dòng)態(tài)數(shù)據(jù),只需要基于appointmentEndTime和當(dāng)前時(shí)間來(lái)計(jì)算倒計(jì)時(shí)。對(duì)于超過(guò)當(dāng)前時(shí)間的數(shù)據(jù),可以直接顯示“已結(jié)束”或其他提示
以下是基于Vue 3的倒計(jì)時(shí)實(shí)現(xiàn)方式,重點(diǎn)是如何根據(jù)appointmentEndTime與當(dāng)前時(shí)間來(lái)動(dòng)態(tài)更新表格的倒計(jì)時(shí)列
- appointmentEndTime 固定:你可以直接在表格數(shù)據(jù)中使用固定的時(shí)間戳。
- 倒計(jì)時(shí)邏輯:通過(guò)setInterval每秒更新一次倒計(jì)時(shí),但如果appointmentEndTime已經(jīng)過(guò)期,就不再更新。
- 無(wú)須請(qǐng)求后端:無(wú)需額外API請(qǐng)求,直接使用appointmentEndTime進(jìn)行計(jì)算
<template> <div> <el-table :data="tableData" style="width: 100%"> <!-- 審核時(shí)間列 --> <el-table-column label="審核時(shí)間" align="center" prop="appointmentReviewTime" :formatter="dateFormatter" width="170px" /> <!-- 還柜時(shí)間列 --> <el-table-column label="還柜時(shí)間" align="center" prop="appointmentEndTime" :formatter="dateFormatter" width="170px" /> <!-- 倒計(jì)時(shí)列 --> <el-table-column label="倒計(jì)時(shí)" 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() { // 表格數(shù)據(jù),appointmentEndTime 是固定的時(shí)間 const tableData = ref([ { appointmentReviewTime: '2024-09-20 12:00:00', appointmentEndTime: '2024-09-20 14:00:00' // 固定時(shí)間 }, { appointmentReviewTime: '2024-09-21 15:00:00', appointmentEndTime: '2024-09-21 17:00:00' // 固定時(shí)間 } ]); // 倒計(jì)時(shí)格式化函數(shù) const formatCountdown = (endTime) => { const now = new Date().getTime(); const endTimestamp = new Date(endTime).getTime(); const remainingTime = endTimestamp - now; // 如果已過(guò)期,返回 "已結(jié)束" if (remainingTime <= 0) { return '已結(jié)束'; } 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}小時(shí) ${minutes}分鐘 ${seconds}秒`; }; // 使用 setInterval 動(dòng)態(tài)更新倒計(jì)時(shí) const intervalId = ref(null); onMounted(() => { intervalId.value = setInterval(() => { // 強(qiáng)制觸發(fā)視圖更新 tableData.value = [...tableData.value]; }, 1000); }); // 清除計(jì)時(shí)器 onBeforeUnmount(() => { clearInterval(intervalId.value); }); return { tableData, formatCountdown }; } }; </script>
如果不會(huì)出現(xiàn)自動(dòng)更新視圖的,需要排查下瀏覽器的終端是否會(huì)有輸出異常
實(shí)戰(zhàn)中的Bug:(錯(cuò)誤信息 queryParams.value is not iterable 表示在某處嘗試遍歷或解構(gòu)了queryParams,但是它不是可迭代的對(duì)象,確保queryParams是一個(gè)對(duì)象或數(shù)組,不能將非迭代對(duì)象進(jìn)行迭代操作)
3. 拓展Demo
appointmentEndTime這個(gè)是timestamp時(shí)間,也就是設(shè)定的未來(lái)時(shí)間
但是我要已過(guò)期,或者超過(guò)當(dāng)前時(shí)間的 都顯示 重新預(yù)約
那么只需要在超過(guò)當(dāng)前時(shí)間或已過(guò)期的情況下顯示“重新預(yù)約”
- 修改 formatCountdown 函數(shù):
在 formatCountdown 函數(shù)中添加一個(gè)返回值,用于標(biāo)記該時(shí)間是否已經(jīng)過(guò)期
const formatCountdown = (endTime) => { const now = new Date().getTime(); const endTimestamp = new Date(endTime).getTime(); const remainingTime = endTimestamp - now; // 如果已過(guò)期,返回 "已過(guò)期" 并標(biāo)記為需要重新預(yù)約 if (remainingTime <= 0) { return { text: '已過(guò)期', 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); // 分時(shí)秒的格式化 return { text: `${hours}小時(shí) ${minutes}分鐘 ${seconds}秒`, isExpired: false }; };
- 修改模板邏輯:
使用 formatCountdown 函數(shù)的返回值來(lái)判斷是否顯示 “重新預(yù)約”
<el-table-column label="還柜剩余時(shí)間" 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']" > 重新預(yù)約 </el-button>
為了在等于當(dāng)前時(shí)間點(diǎn)的時(shí)候觸發(fā)后端請(qǐng)求
可以修改倒計(jì)時(shí)的函數(shù)如下:
// 倒計(jì)時(shí)格式化函數(shù) const formatCountdown = (endTime,id) => { const now = new Date().getTime(); const endTimestamp = new Date(endTime).getTime(); const remainingTime = endTimestamp - now; // 設(shè)置一個(gè)容忍時(shí)間范圍(例如,1秒) const tolerance = 1000; // 1秒 // 當(dāng)時(shí)間接近到達(dá)時(shí),發(fā)送請(qǐng)求到后端更新?tīng)顟B(tài) if (remainingTime <= tolerance && remainingTime > 0) { console.log(1); // 確保能夠輸出 } // 如果已過(guò)期,返回 "已過(guò)期" 并標(biāo)記為需要重新預(yù)約 if (remainingTime < 0) { return { text: '已過(guò)期', 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); // 分時(shí)秒的格式化 return { text: `${hours}小時(shí) ${minutes}分鐘 ${seconds}秒`, isExpired: false }; };
以上的函數(shù)需要注意的點(diǎn)如下:
由于時(shí)間的精確性和計(jì)算方式,remainingTime 很少會(huì)正好等于 0。即使時(shí)間點(diǎn)非常接近,由于毫秒級(jí)的差異,可能導(dǎo)致 remainingTime 不完全等于 0
以上就是Vue3動(dòng)態(tài)倒計(jì)時(shí)的代碼實(shí)現(xiàn)的詳細(xì)內(nèi)容,更多關(guān)于Vue3動(dòng)態(tài)倒計(jì)時(shí)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
- Vue3實(shí)現(xiàn)獲取驗(yàn)證碼按鈕倒計(jì)時(shí)效果
- Vue3+Hooks實(shí)現(xiàn)4位隨機(jī)數(shù)和60秒倒計(jì)時(shí)的示例代碼
- vue3實(shí)現(xiàn)封裝時(shí)間計(jì)算-日期倒計(jì)時(shí)組件-還有XX天&第XX天
- 基于Vue3創(chuàng)建一個(gè)簡(jiǎn)單的倒計(jì)時(shí)組件
- vue3發(fā)送驗(yàn)證碼倒計(jì)時(shí)功能的實(shí)現(xiàn)(防止連點(diǎn)、封裝復(fù)用)
- Vue3?實(shí)現(xiàn)驗(yàn)證碼倒計(jì)時(shí)功能
- Vue3?實(shí)現(xiàn)驗(yàn)證碼倒計(jì)時(shí)功能(刷新保持狀態(tài))
- 使用Vue3實(shí)現(xiàn)倒計(jì)時(shí)器及倒計(jì)時(shí)任務(wù)的完整代碼
相關(guān)文章
vue3+ts+vite+electron搭建桌面應(yīng)用的過(guò)程
這篇文章主要介紹了vue3+ts+vite+electron搭建桌面應(yīng)用的過(guò)程,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-04-04使用webpack手動(dòng)搭建vue項(xiàng)目的步驟
這篇文章主要介紹了從零使用webpack手動(dòng)搭建vue項(xiàng)目的步驟,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-03-03Vue項(xiàng)目通過(guò)network的ip地址訪(fǎng)問(wèn)注意事項(xiàng)及說(shuō)明
這篇文章主要介紹了Vue項(xiàng)目通過(guò)network的ip地址訪(fǎng)問(wèn)注意事項(xiàng)及說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-09-09vue實(shí)現(xiàn)滑動(dòng)到底部加載更多效果
這篇文章主要為大家詳細(xì)介紹了vue實(shí)現(xiàn)滑動(dòng)到底部加載更多效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-08-08解決element-ui的el-select選擇器的@blur事件失效的坑
這篇文章主要介紹了解決element-ui的el-select選擇器的@blur事件失效的坑,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-09-09vue2和el-input無(wú)法修改和寫(xiě)入并且不報(bào)錯(cuò)的解決方案
這篇文章主要介紹了vue2和el-input無(wú)法修改和寫(xiě)入并且不報(bào)錯(cuò)的解決方案,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2024-07-07