articles
articles copied to clipboard
滚动防抖引发的一个莫名其妙的bug
问题描述
一开始这个 bug
是在 weex
下遇到的,使用的是 weex
自己的 scroller
组件,需要对滑动操作做防抖,会出现3s左右的延迟。
问题定位
做了几个组合实验来排除可能性:
-
weex
滚动组件@scroll+setTimeout
(会出现) -
[email protected]+setTimeout
(单独测试不会出现,项目中会出现) -
weex
滚动组件@scroll.native+setTimeout
(会出现)
剥离业务代码后的代码如下:
let timeout = 0;
let time = '';
export default {
methods: {
onScroll() {
time = Date.now();
console.log('滚动', time);
clearTimeout(timeout);
timeout = setTimeout(() => {
time = Date.now();
console.log('触发', time);
}, 1000);
},
},
};
setTimeout(() => {}, delay)
中 delay
设置超过3s就是正常设置的时间,如果设置的 delay
小于3s,就会出现3s延迟。
setTimeout(() => {}, 0)
也会出现这个问题,setImmediate()
不会出现这个问题,但是就不起防抖的作用。
然而没有找出问题所在。。。
解决方法
暂时使用 requestAnimationFrame
替代 setTimeout
。
setRaf() {
this.raf = requestAnimationFrame(() => {
this.rafTimes += 1;
if (this.rafTimes >= 20) {
this.scrollBody(); // 触发实际滚动方法
this.rafTimes = 0;
} else {
this.setRaf();
}
});
},
onScroll() {
if (requestAnimationFrame) {
this.rafTimes = 0;
cancelAnimationFrame(this.raf);
this.setRaf();
} else {
this.scrollBody(); // 触发实际滚动方法
}
},
由于 requestAnimationFrame
存在兼容性问题,首先需要进行一下判断:
const requestAnimationFrame = window.requestAnimationFrame || window.webkitRequestAnimationFrame;
const cancelAnimationFrame = window.cancelAnimationFrame || window.webkitCancelAnimationFrame || window.webkitCancelRequestAnimationFrame;
最好的方式应该是要对 requestAnimationFrame
进行 polyfill
的,但是 requestAnimationFrame
的 polyfill
会用到 setTimeout
,还是会延时,所以在不支持 requestAnimationFrame
的环境下只能不做防抖了。
求助
如果有谁知道这是为什么的,一定一定要告诉我 ~ 谢谢 ~