1.防抖:触发高频事件后n秒内函数只会执行一次,如果n秒内高频事件再次被触发,则重新计算时间。
思路:每次触发事件时都取消之前的延时调用方法。
/*
fn:事件处理函数
delay:定时器延时
rest:传参给事件处理函数
*/
function debounce (fn, delay,...rest) {
let timeout = null;
return function (e) {
// e:事件对象
if (timeout) { clearTimeout(timeout) };//把前面那个timeout清除
timeout = setTimeout(()=>{
console.log(e, rest);
console.log(this);
fn.apply(this, [e, ...rest]);// 绑定this指向
}, delay);
}
}
function sayHi(e, ...rest) {
console.log(e, rest);
console.log(this.value);
}
var inp = document.getElementById('inp');
inp.addEventListener('input', debounce(sayHi, 300, 100, 200));
2.节流:高频事件触发,但在n秒内只执行一次,所以节流会稀释函数的执行频率。
思路:每次触发事件时都判断当前是否有等待执行的延时函数。
function throttle(fn) {
let canRun = true; // 通过闭包保存一个标记
return function () {
if (! canRun) return; // 在函数开头判断标记是否为true,不为true则return
canRun = false; // 立即设置为false
setTimeout(() => { // 将外部传入的函数的执行放在setTimeout中
fn. apply (this, arguments);
// 最后在setTimeout执行完毕后再把标记设置为true(关键)表示可以执行下一次循环了。当定时器没有执行的时候标记永远是false,在开头被return掉
canRun = true;
}, 500);
};
}
function sayHi(e) {
console.log (e. target. innerWidth, e. target. innerHeight);
}
window. addEventListener ('resize', throttle(sayHi));
场景分析:
- 搜索框input事件,具体使用哪种方案要看业务需求
-
- 要支持输入实时搜索可使用节流,间隔一段时间就查询相关内容;
- 要支持输入完成后搜索可使用防抖。
-
- 页面resize事件,常见于需要做页面适配,需根据最终呈现的页面情况进行DOM渲染,这种情形一般是使用防抖,因为只需要判断最后一次的变化情况。