手动实现防抖
和节流
防抖:事件被触发 n 秒后再执行回调,如果在这 n 秒内事件又被触发,则重新计时,,防止在短时间内过于频繁的执行相同的任务。当短时间内的频繁是不必要的时候,就可以考虑去抖动,避免资源浪费,或造成不友好的体验。
节流:规定一个单位时间,在这个单位时间内,只能有一次触发事件的回调函数执行,如果在同一个单位时间内某事件被触发多次,只有一次能生效
防抖函数的应用场景:
- 按钮提交场景:防⽌多次提交按钮,只执⾏最后提交的⼀次
- 服务端验证场景:表单验证需要服务端配合,只执⾏⼀段连续的输⼊事件的最后⼀次,还有搜索联想词功能类似⽣存环境请⽤lodash.debounce
节流函数的适⽤场景:
- 拖拽场景:固定时间内只执⾏⼀次,防⽌超⾼频次触发位置变动
- 缩放场景:监控浏览器resize
- 动画场景:避免短时间内多次触发动画引起性能问题
js
/**
* debounce 防抖
* @param fn [function] 需要防抖的函数
* @param delay [number] 毫秒,防抖期限值
*/
function debounce(fn, delay) {
let timer = null; //借助闭包
return function (...arg) {
if (timer) {
//进入该分支语句,说明当前正在一个计时过程中,并且又触发了相同事件。
// 所以要取消当前的计时,重新开始计时
clearTimeout(timer);
}
timer = setTimeout(() => {
fn.apply(this, arg); // 使用apply将fn函数的this指向修改为return后的function
}, delay); // 进入该分支说明当前并没有在计时,那么就开始一个计时
};
}
js
/**
* throttle 节流
* @param fn [function] 需要节流的函数
* @param delay [number] 毫秒
*/
function throttle(fn, delay) {
let valid = false; // 节流阀
return function (...arg) {
if (valid) {
//休息时间 暂不接客
return;
}
// 工作时间,执行函数并且在间隔期内把状态位设为无效
valid = true;
setTimeout(() => {
fn.apply(this, arg);
valid = false;
}, delay);
};
}