防抖与节流
汤姆不是猫 ... 2021-11-05 大约 1 分钟
# 防抖(debounce)
# 🤯 防抖原理:
如果短时间内大量触发同一事件,只会执行一次函数。
在事件被触发n秒后再执行回调,如果在这n秒内又触发,则重新计时。
# 🤔 适用场景:
按钮提交场景:防止多次执行提交,只执行最后一次提交;
服务端验证场景:表单实时验证,只执行连续输入事件的最后一次(类搜索联想词);
# 😃 简化版实现:
const debounce = (fn, delay = 500) => {
let timeout = null;
return (...args) => {
clearTimeout(timeout);
timeout = setTimeout(() => {
fn.apply(this, args);
}, delay);
}
}
let sayDebounce = () => {
console.log('防抖成功')
}
window.addEventListener('scroll', debounce(sayDebounce))
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 节流(throttle)
# 🤯 节流原理:
如果短时间内大量触发同一事件,那么在函数执行一次之后,该函数在指定的时间期限内不再工作,直至过了这段时间才重新生效。
# 🤔 适用场景:
拖拽场景:固定时间内只允许拖动一次,防止超高频词触发位置变动;
缩放场景:监视浏览器的resize;
动画场景:避免短时间内多次触发动画引起性能问题;
# 😃 简化版实现:
// ①定时器实现
const throttle = (fn, delay = 500) =>{
let flag = true;
return (...args) => {
if(!flag) return;
flag = false;
setTimeout(() => {
fn.apply(this, args);
flag = true;
}, delay);
};
}
// ②时间戳实现
const throttle = (fn, delay = 500) => {
let preTime = Date.now();
return (...args) => {
const nowTime = Date.now();
if(nowTime - preTime >= delay) {
preTime = Date.now();
fn.apply(this, args);
}
}
}
let sayThrottle = (e) => {
console.log(e.target.innerWidth, e.target.innerHeight)
}
window.addEventListener('resize', throttle(sayThrottle))
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30