Vue3動態(tài)倒計時的代碼實現(xiàn)
1. Demo
給一版初始的Demo,在給一版實戰(zhàn)中的Demo
基本知識點:
- Vue 3 的響應式原理:Vue 3 使用 reactive 和 ref 創(chuàng)建響應式數(shù)據(jù),數(shù)據(jù)的變化會自動觸發(fā)視圖更新
- setup 函數(shù):Vue 3 引入了 Composition API,其中的 setup 函數(shù)是組件邏輯的入口
- watch 偵聽器:用于偵聽響應式數(shù)據(jù)的變化,在倒計時場景中可以用于監(jiān)聽時間的變化
- 生命周期鉤子:如 onMounted 和 onUnmounted 用于在組件掛載和銷毀時啟動和清理倒計時
- setInterval 和 clearInterval:用于每隔一段時間執(zhí)行倒計時任務
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. 實戰(zhàn)Demo
本身倒計時的某一列時間是固定的,那就不需要通過后端來獲取動態(tài)數(shù)據(jù),只需要基于appointmentEndTime和當前時間來計算倒計時。對于超過當前時間的數(shù)據(jù),可以直接顯示“已結束”或其他提示
以下是基于Vue 3的倒計時實現(xiàn)方式,重點是如何根據(jù)appointmentEndTime與當前時間來動態(tài)更新表格的倒計時列
- appointmentEndTime 固定:你可以直接在表格數(shù)據(jù)中使用固定的時間戳。
- 倒計時邏輯:通過setInterval每秒更新一次倒計時,但如果appointmentEndTime已經(jīng)過期,就不再更新。
- 無須請求后端:無需額外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() {
// 表格數(shù)據(jù),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' // 固定時間
}
]);
// 倒計時格式化函數(shù)
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 動態(tài)更新倒計時
const intervalId = ref(null);
onMounted(() => {
intervalId.value = setInterval(() => {
// 強制觸發(fā)視圖更新
tableData.value = [...tableData.value];
}, 1000);
});
// 清除計時器
onBeforeUnmount(() => {
clearInterval(intervalId.value);
});
return {
tableData,
formatCountdown
};
}
};
</script>

如果不會出現(xiàn)自動更新視圖的,需要排查下瀏覽器的終端是否會有輸出異常
實戰(zhàn)中的Bug:(錯誤信息 queryParams.value is not iterable 表示在某處嘗試遍歷或解構了queryParams,但是它不是可迭代的對象,確保queryParams是一個對象或數(shù)組,不能將非迭代對象進行迭代操作)

3. 拓展Demo
appointmentEndTime這個是timestamp時間,也就是設定的未來時間
但是我要已過期,或者超過當前時間的 都顯示 重新預約
那么只需要在超過當前時間或已過期的情況下顯示“重新預約”
- 修改 formatCountdown 函數(shù):
在 formatCountdown 函數(shù)中添加一個返回值,用于標記該時間是否已經(jīng)過期
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 函數(shù)的返回值來判斷是否顯示 “重新預約”
<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>

為了在等于當前時間點的時候觸發(fā)后端請求
可以修改倒計時的函數(shù)如下:
// 倒計時格式化函數(shù)
const formatCountdown = (endTime,id) => {
const now = new Date().getTime();
const endTimestamp = new Date(endTime).getTime();
const remainingTime = endTimestamp - now;
// 設置一個容忍時間范圍(例如,1秒)
const tolerance = 1000; // 1秒
// 當時間接近到達時,發(fā)送請求到后端更新狀態(tài)
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 };
};
以上的函數(shù)需要注意的點如下:
由于時間的精確性和計算方式,remainingTime 很少會正好等于 0。即使時間點非常接近,由于毫秒級的差異,可能導致 remainingTime 不完全等于 0
以上就是Vue3動態(tài)倒計時的代碼實現(xiàn)的詳細內(nèi)容,更多關于Vue3動態(tài)倒計時的資料請關注腳本之家其它相關文章!
相關文章
vue3+ts+vite+electron搭建桌面應用的過程
這篇文章主要介紹了vue3+ts+vite+electron搭建桌面應用的過程,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-04-04
解決element-ui的el-select選擇器的@blur事件失效的坑
這篇文章主要介紹了解決element-ui的el-select選擇器的@blur事件失效的坑,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-09-09
vue2和el-input無法修改和寫入并且不報錯的解決方案
這篇文章主要介紹了vue2和el-input無法修改和寫入并且不報錯的解決方案,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友參考下吧2024-07-07

