直接进入正题,有的时候使用scroll或者mousemove这类函数并不需要那么频繁的调用这些函数,举个栗子,dom的mousemove 事件。
<div id="content"
style="height:800px;width:800px;line-height:400px;text-align:center; color: rgb(0, 0, 0);background-color:rgb(134, 70, 70);font-size:80px;font-weight: 800;"></div>
<script>
let num = 1;
let content = document.getElementById('content');
content.onmousemove = ()=>{
content.innerHTML = num++;
};
</script>
在有些业务下显然是不合理的,比如监听访问后的网络请求, 只要请求速度跟不上响应的速度,那么肯定会有卡顿的情况发生,以下有几种解决办法
防抖(debounce)
多次访问函数,最终变成一次执行的方式
1.通过不断重置setTimeout的时间来让方法延迟执行,show code follow
let num = 1;
let content = document.getElementById('content');
function move() {
content.innerHTML = num++;
}
content.onmousemove = debounce(move, 1000)
//第一次访问设置1000的timeout,以后每次访问都是由apply来引导到当前this的函数(也就是debounce)重置timeout
function debounce(func, wait) {
let timeout;
return function () {
let context = this;
let args = arguments;
if (timeout) clearTimeout(timeout);
timeout = setTimeout(() => {
func.apply(context, args)
}, wait);
}
}
解释在注释,业务中当鼠标停住后,最后一次延时计时1000ms,然后move()
节流(throttle )
1.对比前后两次的时间戳,间隔很小取消执行,间距很大即可执行,show code follow
let num = 1;
let content = document.getElementById('content');
function move() {
content.innerHTML = num++;
}
content.onmousemove = throttle(move, 1000)
function throttle(func, wait) {
var context, args;
var previous = 0;
return function() {
var now = +new Date();
context = this;
args = arguments;
if (now - previous > wait) {
func.apply(context, args);
previous = now;
}
}
}
2.setTimeout定时器也可以达到效果相同的节流效果,show code follow
let num = 1;
let content = document.getElementById('content');
function move() {
content.innerHTML = num++;
}
content.onmousemove = throttle(move, 1000)
function throttle1(func, wait) {
var timeout;
var previous = 0;
return function () {
context = this;
args = arguments;
if (!timeout) {
timeout = setTimeout(function () {
timeout = null;
func.apply(context, args)
}, wait)
}
}
}
但是这两种节流的实现方法还是有很大区别的
一、
第一种对比时间戳是一旦满足空挡时间即刻执行,
第二种是定时器控制定时完成后再去执行函数,有本质上的区别
PS:假如空隙为3s,第一种会立即执行第一次,第二种会3s后执行第一次、
二、
一种事件停止触发后没有办法再执行事件,第二种事件停止触发后依然会再执行一次事件
附上原文链接,欢迎大家讨论
https://github.com/mqyqingfeng/Blog/issues/22