小程序倒计时重叠抖动问题
因为请求数据写在 onShow 函数里面,所以每次切换界面都会刷新,这就会导致,如果当前 定时器在跑的话,再次刷新会再次常见定时,那么就会导致刷新几次有几个定时器,同时在跑,那么前端界面显示的计时数字 就会不时跳动,所以需要保证在跑的定时器只有一个。将定时器对象创建为全局的,在每次开启定时器的时候先清空之前的定时器。就可以解决刷新后计时闪动的问题了,或者在在 tab 页面,运用 onHide 周期 进行 clearTimeInterval 清空 , 在 非 tab 页面,运用 onUload() 周期 进行 clearTimeInterval 清空,百度都可以找到类似解决方案,其中在我的历史文章小程序实战踩坑之 B2B 商城项目总结也有总结,代码类似如下:
/**
* 清除 interval
* @param that
*/
clearTimeInterval: function (that) {
var interval = that.data.interval;
clearInterval(interval)
},
/**
* 生命周期函数 – 监听页面卸载
* 退出本页面时停止计时器
*/
onUnload:function () {
var that = this;
that.clearTimeInterval(that)
},
/**
* 生命周期函数 – 监听页面隐藏
* 在后台运行时停止计时器
*/
onHide:function () {
var that = this;
that.clearTimeInterval(that)
}
倒计时使用 setInterval 或 setTimeout 触摸屏幕导致时间显示的突跳,突慢问题,卡顿,甚至停止
不信的同学,可以尝试用手指触摸屏幕,上下小幅上下移动不放,你会发觉时间竟然停止了。(特别是针对低端机型)
通常同学写代码都会如此:
let self = this;
let lefttimeSec = time – new Date().getTime();
let calc = setInterval(function() {
lefttimeSec -= 1000;
self.endtimestr = ‘ 距离拼单结束还有 ’ + self.dateformat(lefttimeSec);
self.$apply();
if (lefttimeSec <= 0) {
clearInterval(calc);
}
}, 1000);
使用 setInterval 后,即使用了上面说的“小程序倒计时重叠抖动问题”解决方案,只是解决了倒计时重叠问题,这样写法,会导致的一些精准度不高。其实很简单,解决代码如下:
showCountTime(time){
let self = this;
setTimeout(function(){
let lefttimeSec = time – new Date().getTime();
lefttimeSec -= 1000;
self.endtimestr = ‘ 距离拼单结束还有 ’ + self.dateformat(lefttimeSec);
self.$apply();
self.showCountTime(time);
},1000);
}
注意,这里用了 setTimeout,要 tab 页面,运用 onHide 周期进行 clearTimeout 清空, 在非 tab 页面,运用 onUload() 周期 进行 clearTimeout 清空定时器。这步必须要做,就不多说了,要不还是会出现上面说的“小程序倒计时重叠抖动问题”问题。
用了上面代码,补失的精准度不足。小心的测试同学会发现触摸屏幕导致的突跳,突慢问题, 甚至停止!于是各种寻思,去找了拼多多小程序,京东购物小程序各种对比。结论是拼多多存在和我一样的问题,京东购物小程序的倒计时没这样的问题,给个赞!
出现问题环境描述:
小程序框架:wepy : “^1.7.2″
测试机型:红米 3
自身思路是 wepy 脏检查在触摸(滚动)屏幕下引起性能占用导致的一些效率不足问题,做了进一步测试,还是用红米 3 机型,抛掉组件,抛掉 data,只保留 data,做一个简单的渲染,将页面高度固定,让屏幕可以上下滑动,代码如下:
<style>
.content {
height: 2000rpx;
border: 1rpx solid red;
}
.child {
height: 500rpx;
}
</style>
<template>
<view class=”content”>
<view class=”child”></view>
{{endtimestr}}
</view>
</template>
<script>
import wepy from ‘wepy’;
export default class test extends wepy.page {
data = {
endtimestr: ”
}
showCountTime(time) {
let self = this;
setTimeout(function() {
let lefttimeSec = time – new Date().getTime();
lefttimeSec -= 1000;
self.endtimestr = ‘ 距离拼单结束还有 ’ + self.dateformat(lefttimeSec);
self.$apply();
self.showCountTime(time);
}, 1000);
}
dateformat = (micro_second) => {
// 总秒数
var second = Math.floor(micro_second / 1000);
// 天数
var day = Math.floor(second / 3600 / 24);
// 小时
var hr = Math.floor(second / 3600 % 24);
// 分钟
var min = Math.floor(second / 60 % 60);
// 秒
var sec = Math.floor(second % 60);
hr = hr < 10 ? ‘0’ + hr : hr;
min = min < 10 ? ‘0’ + min : min;
sec = sec < 10 ? ‘0’ + sec : sec;
if (day > 0) {
return day + ” 天 ” + ‘ ‘ + hr + “:” + min + “:” + sec;
} else {
return hr + “:” + min + “:” + sec;
}
}
onLoad() {
//api 模拟得到 time
this.showCountTime(1545899950167);
}
}
</script>
结论是:倒计时在触摸(滚动)情况下正常了!!!那也表明 wepy 的脏检查存在一些性能的不足呀,希望未来 wepy 有改进!