节流和防抖 区别和实现
节流
实现:
/**
* 函数节流:开始会执行一次,持续触发事件的话,每隔wait时间执行一次;
* 应用场景mousemove, scroll等会连续执行的事件,比较适合应用于动画相关的场景。
* @param fn 需要节流的函数
* @param wait 间隔时间
*/
export function throttle(fn, wait = 1000) {
let lastTime = 0; //上次执行的时间
return function (...args) {
let now = +new Date();
if (now - lastTime > wait) {
lastTime = now;
fn.apply(this, args);
}
}
}
使用:
mounted() {
// 触发resize的时候会先执行一次,如果下次触发resize和上次触发resize时间大于wait(不论中间有没有持续触发resize),那么会再次执行函数
window.addEventListener(
"resize",
(this._resize = throttle(()=>{console.log("视口改变")}, 5000))
);
},
destroyed() {
window.removeEventListener("resize", this._resize);
}
防抖
实现:
/**
* 函数防抖:触发事件的wait 时间后才执行; 如果wait 时间内事件持续被触发,则以新触发的时间为标准,然后wait 时间后再执行;
(不持续触发,wait 时间后执行一次;如果持续触发,以最后触发为准,也wait 时间后只执行一次)
* 应用场景: 输入验证,提交按钮点击事件
* @param fn 需要防抖的函数
* @param wait 等待时间
*/
function debounce(fn, wait = 1000) {
let timer = undefined; //定时器id
return function (...args) {
if (timer) clearTimeout(timer);
timer = setTimeout(() => {
fn.apply(this, args);
}, wait);
}
}
说明
以上持续触发是指wait时间内触发两次以上:
不持续触发时(wait时间内只触发一次): 节流只在触发时执行一次;防抖会在触发事件wait时间后执行一次;
持续触发(wait时间内触发两次以上): 节流在每一个wait时间开始都会执行一次;防抖会在最后一次触发的wait时间后只执行一次
节流和防抖解释起来比较混乱,要自己多去使用,并结合实现的代码,才慢慢会有所体会。
这里推荐一篇司徒正美的节流和防抖文章