参考地址:https://www.cnblogs.com/zyfenblog/p/11104053.html
参考地址:https://www.dazhuanlan.com/2019/12/09/5dedc6f6d756b/
参考地址:https://blog.csdn.net/my_atlassian_yhl/article/details/81166488
我们先看下最后实现的效果
- 进入秒杀页面,初始化倒计时都是00天00时00分00秒
- 计算倒计时,判断当前时间是否小于倒计时开始时间,如果小于则显示倒计时,否则显示活动进行中,当活动结束时后台就会把对应商品清除
跳转到下一个页面不清空倒计时,返回首页时清空倒计时,再进入秒杀页面时重新初始化倒计时(因为重新获取了列表数据)
思路:
核心是加载列表数据之后,统一维护一个倒计时,伪造同时进行倒计时,每秒钟为这个数组中的每一个时间减一秒
- 如果所有的列表倒计时都结束了,那就清除倒计时
- 下拉刷新需要重新获取数据,这个时候需要清除倒计时
倒计时存放到app.js全局数据中,这样可以在别的页面清除倒计时
具体实现:
// app.js
App({
globalData: {
seckillTimer: null, // 秒杀计时器
},
)
```javascript // 具体实现页面 onLoad: function (options) { // 进入页面请求列表数据 this.seckillInfoPage() }, seckillInfoPage() { wx.showLoading(); app.api.seckillInfoPage(Object.assign( {}, this.data.page, util.filterForm(this.data.parameter) )) .then(res => {
let seckillInfoList = res.data.records
// 请求到的分页列表数据
let list = [...this.data.seckillInfoList, ...seckillInfoList]
console.log(list);
list.map(item => { // 给每个列表项初始化倒计时
item.validBeginStr = `00天00时00分00秒`
})
// 先更新数据进行显示,这个时候可能倒计时正在计算
this.setData({
seckillInfoList: list
})
// 开始计算倒计时
this.countdown()
}) },
// 倒计时(核心方法) countdown() { let that = this let list = this.data.seckillInfoList app.globalData.seckillTimer = setInterval(function () { for (let i = 0; i < list.length; i++) {
// console.log(list[i]);
let nowDate = new Date().getTime()
let t = list[i].validBegin - nowDate
t -= 1000
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)
/* var day = parseInt(t / 1000 / 60 / 60 / 24, 10)
var hour = parseInt(t / 1000 / 60 / 60 % 24, 10)
var min = parseInt(t / 1000 / 60 % 60, 10)
var sec = parseInt(t / 1000 % 60, 10) */
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}秒`
list[i].validBeginStr = format
} else {
// 进行判断 如果数据内所有的倒计时已经结束,那么结束定时器, 如果没有那么继续执行定时器
let flag = list.every((val, ind) => val.validBegin <= 0)
if (flag) clearInterval(app.globalData.seckillTimer)
list[i].validBeginStr = `秒杀进行中` // 结束文案
}
} wx.hideLoading(); that.setData({ //重新更新列表
seckillInfoList: list
}) }, 1000) },
refresh() { this.setData({ loadmore: true, seckillInfoList: [],
['page.current']: 1
})
// 列表下拉刷新时,清除倒计时
clearInterval(app.globalData.seckillTimer)
this.seckillInfoPage()
}, onPullDownRefresh() { // 显示顶部刷新图标 wx.showNavigationBarLoading() this.refresh() // 隐藏导航栏加载框 wx.hideNavigationBarLoading() // 停止下拉动作 wx.stopPullDownRefresh() }
```javascript
// home.js
const app = getApp()
Page({
onShow() {
// 每次进入首页,认为是重新进入应用,清空倒计时,
if (app.globalData.seckillTimer) {
clearInterval(app.globalData.seckillTimer)
}
},
})
<wxs module="dateUtil" src="../../../utils/dateUtil.wxs"></wxs>
<view class="cu-card article no-card">
<view class="cu-item" wx:for="{{ seckillInfoList }}" wx:key="index">
<view class="content">
<view class="card_left margin-right-sm">
<image src="{{item.picUrl}}" mode="aspectFill" class="row-img margin-top-xs" />
// 循环显示倒计时
<view class="countdown">{{item.validBeginStr}}</view>
</view>
<view class="desc row-info solid-bottom padding-bottom">
<view class="text-black margin-top-sm overflow-2">{{item.name}}</view>
<view class="flex justify-start margin-top-sm">
<view class="text-price text-bold text-red">{{item.seckillPrice}}</view>
<view class="text-price text-decorat text-sm text-gray margin-left-sm">{{item.goodsSku.salesPrice}}</view>
<view class="cu-tag bg-red radius sm margin-left" wx:if="{{item.goodsSpu.freightTemplat.type == '2'}}">包邮</view>
</view>
<view class="flex justify-end margin-top-sm">
<view class="text-sm text-gray margin-left-sm">已有{{item.launchNum}}人参与</view>
</view>
<view class="flex justify-center margin-top">
<navigator class="cu-btn round bg-red" hover-class="none" url="/pages/seckill/seckill-detail/index?id={{item.id}}">立刻秒杀</navigator>
</view>
</view>
</view>
</view>
</view>
<view wx:if="{{seckillInfoList.length}}" class="cu-load bg-gray {{loadmore?'loading':'over'}}"></view>