本文介绍在Vue环境中实现多个商品并行倒计时的方法。通过统一定时器循环更新数据对象中的时间戳,避免为每个商品创建独立定时器。重点解决切换路由时未结束倒计时仍占用性能的问题,利用destroyed生命周期将剩余时间置零并清理状态,提升用户体验。
多商品并行倒计时需求分析
在处理类似拼团场景时,往往需要为列表中的多个商品分别设置独立的倒计时。起初面对这一需求时,若商品数量较少,直接编写固定变量并创建多个定时器即可解决。
然而,实际业务中的数据是动态变化的。参考主流拼团应用的功能实现,本文基于Vue环境探讨如何实现这一功能。
数据准备与基础方法
首先,我们需要构建用于渲染的静态测试数据,以模拟后端返回的商品列表结构。
data () {
return {
list: [ // 准备渲染的数据
{
remainTime: 900000, // 距离结束还有多久
remainTimeStr: '' // 展示文案
},
{
remainTime: 400000,
remainTimeStr: ''
},
{
remainTime: 60500,
remainTimeStr: ''
},
]
}
}
接着,从网络资源中获取一个基础的倒计时计算方法作为参考。
countdowm (timestamp) {
let self = this
let timer = setInterval(function () {
let nowTime = new Date()
let endTime = new Date(timestamp)
let t = endTime.getTime() - nowTime.getTime()
if (t > 0) {
let day = Math.floor(t / 86400000)
let hour = Math.floor((t / 3600000) % 24)
let min = Math.floor((t / 60000) % 60)
let sec = Math.floor((t / 1000) % 60)
hour = hour < 10 ? '0' + hour : hour
min = min < 10 ? '0' + min : min
sec = sec < 10 ? '0' + sec : sec
let format = ''
if (day > 0) {
format = `${day}天${hour}小时${min}分${sec}秒`
}
if (day <= 0 && hour > 0) {
format = `${hour}小时${min}分${sec}秒`
}
if (day <= 0 && hour <= 0) {
format = `${min}分${sec}秒`
}
self.content = format
} else {
clearInterval(timer)
self.content = 'over'
}
}, 1000)
}
在深入编码前,需梳理清楚整体逻辑流程。
倒计时逻辑优化与实现
核心思路是优化原有的倒计时方法。我们不再依赖获取当前时间与结束时间的差值,而是直接使用距离结束的时间戳。通过一个统一的定时器来并行处理多个倒计时,因此需要对原方法进行改造。
- 优化后的方法不再需要每次获取当前系统时间。
- 同时也省去了复杂的时间计算步骤。
- 由于涉及多个倒计时并行运行,清除定时器的逻辑也需要相应调整,以确保资源正确释放。
countdowm (timestamp) {
let self = this
let timer = setInterval(function () {
let t = timestamp
if (t > 0) {
let day = Math.floor(t / 86400000)
let hour = Math.floor((t / 3600000) % 24)
let min = Math.floor((t / 60000) % 60)
let sec = Math.floor((t / 1000) % 60)
day = day < 10 ? '0' + day : day
hour = hour < 10 ? '0' + hour : hour
min = min < 10 ? '0' + min : min
sec = sec < 10 ? '0' + sec : sec
let format = ''
format = `${day}天${hour}小时${min}分${sec}秒`
self.content = format
} else {
// clearInterval(timer)
self.content = 'over'
}
}, 1000)
}
完成简化后,将上述思路整合进具体的方法实现中。
在定时器内部执行循环,每次迭代将当前数据中的remainTime时间戳减去1000毫秒(即一秒),从而驱动倒计时更新。
countdown () {
let self = this
let timer = setInterval(function () {
for (let i = 0; i < self.list.length; i++) {
self.list[i].remainTime -= 1000
let t = self.list[i].remainTime
if (t > 0) {
let day = Math.floor(t / 86400000)
let hour = Math.floor((t / 3600000) % 24)
let min = Math.floor((t / 60000) % 60)
let sec = Math.floor((t / 1000) % 60)
day = day < 10 ? '0' + day : day
hour = hour < 10 ? '0' + hour : hour
min = min < 10 ? '0' + min : min
sec = sec < 10 ? '0' + sec : sec
let format = ''
format = `距离结束:<b>${day}</b> 天 <b>${hour}</b>
时 <b>${min}</b> 分 <b>${sec}</b> 秒`
self.list[i].remainTimeStr = format
} else {
// 进行判断 如果数据内所有的倒计时已经结束,那么结束定时器, 如果没有那么继续执行定时器
let flag = self.list.every((val, ind) =>
val.remainTime <= 0)
if (flag) clearInterval(timer)
self.list[i].remainTimeStr = `距离结束:<b>00</b> 天
<b>00</b> 时 <b>00</b> 分 <b>00</b> 秒` // 结束文案
}
}
}, 1000)
}
路由切换时的资源清理
至此,多个并行定时器的基本功能已实现。但发现一个潜在问题:当用户切换路由时,若倒计时尚未结束,定时器仍在后台运行,这会造成不必要的性能损耗。尽管用户不可见,但为提升浏览体验,需在页面切换时进行处理。具体做法是在Vue的生命周期函数中,将相关数据重置为0,从而停止倒计时逻辑。
destroyed () {
this.list.forEach((val) => {
val.remainTime = 0
})
}
以上即为该技术方案的全部内容,希望能为相关开发者提供借鉴,欢迎继续支持本站获取更多技术分享。