该篇博文借鉴了前辈的博客,仅用于记录学习
https://www.jianshu.com/p/c8b86b09daf0
在react框架中,给我们提供了防抖和节流的库,可以直接使用,请跳转下方博文
react中的防抖和节流,大佬封装的方法用起来就是爽
防抖和节流
我们经常在开发过程中因为高触发频率,使程序运行产生某些问题,防抖和节流是针对触发频率这类问题的两种解决方案。
在给DOM绑定事件时,有些事件我们是无法控制触发频率的。 如鼠标移动事件onmousemove
, 滚动滚动条事件onscroll
,窗口大小改变事件onresize
,瞬间的操作都会导致这些事件会被高频触发。 如果事件的回调函数较为复杂,就会导致响应跟不上触发,出现页面卡顿,假死现象。
//Html:
<div id="content" style="height:150px;line-height:150px;text-align:center; color: #fff;background-color:#ccc;font-size:80px;"></div>
//Script:
let num = 1;
let content = document.getElementById('content');
function count() {
content.innerHTML = num++;
};
content.onmousemove = count;
防抖(debounce)
触发事件后在 n 秒内函数只能执行一次,如果在 n 秒内又触发了事件,则会重新计算函数执行时间。这是debounce的基本思想,在后期又扩展了前缘debounce,即执行动作在前,然后设定周期,周期内有事件被触发,不执行动作,且周期重新设定。
延迟debounce,是在周期结束时执行,前缘debounce,是在周期开始时执行。但当触发有间断,且间断大于我们设定的时间间隔时,动作就会有多次执行。
-
延迟(debounce)
在这里插入图片描述
content.onmousemove = debounce(count, 500);
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);
}
}
上述防抖函数的代码还需要注意的是 this 和 参数的传递
let context = this;
let args = arguments;
防抖函数的代码使用这两行代码来获取this
和 参数,是为了让 debounce 函数最终返回的函数 this 指向不变以及依旧能接受到 e 参数。
2.前缘debounce
function debounce(func,wait) {
let timeout;
return function () {
let context = this;
let args = arguments;
if (timeout) clearTimeout(timeout);
let callNow = !timeout;
timeout = setTimeout(() => {
timeout = null;
}, wait)
if (callNow) func.apply(context, args)
}
}
节流(throttling)
连续触发事件但是在 n 秒中只执行一次函数。节流会稀释函数的执行频率。与debounce类似,延迟是指 周期结束后执行动作,前缘是指执行动作后再开始周期。
throttling的特点在连续高频触发事件时,动作会被定期执行,响应平滑。
延迟throttling
content.onmousemove = throttle(count, 500);
function throttle(func, wait) {
let timeout;
return function() {
let context = this;
let args = arguments;
if (!timeout) {
timeout = setTimeout(() => {
timeout = null;
func.apply(context, args)
}, wait)
}
}
}
前缘throttling
function throttle(func, wait) {
let previous = 0;
return function() {
let now = Date.now();
let context = this;
let args = arguments;
if (now - previous > wait) {
func.apply(context, args);
previous = now;
}
}
}
防抖和节流各有特点,在不同的场景要根据需求合理的选择策略。如果事件触发是高频但是有停顿时,可以选择防抖;在事件连续不断高频触发时,只能选择节流,因为防抖可能会导致动作只被执行一次,界面出现跳跃。
该篇文章参考了多位前辈的总结,如果涉及侵权,请联系我删除。