一、是什么
1.1 防抖:
就是指触发事件后,在 n 秒内函数只能执行一次,如果触发事件后在 n 秒内又触发了事件,则会重新计算函数延执行时间。
例如:坐电梯的时候,如果电梯检测到有人进来(触发事件),就会多等待 10 秒,此时如果又有人进来(10秒之内重复触发事件),那么电梯就会再多等待 10 秒。
在上述例子中,电梯在检测到有人进入 10 秒钟之后,才会关闭电梯门开始运行,因此,“函数防抖”的关键在于,在 一个事件 发生 一定时间 之后,才执行 特定动作。
1.2 节流
当持续触发事件时,保证一定时间段内只调用一次事件处理函数。
二、实现
2.1 防抖
实现方式:定时器。
// 防抖-n触发一次,如再触发再重新计时。
function debounce(fn, delay) {
if (typeof fn != 'function') {
throw new TypeError('FUN_ERROR_TEXT');
}
let timer = null; // 计时器
return function () {
if (timer) {
clearTimeout(timer) // 进入该分支语句,说明当前正在一个计时过程中,并且又触发了相同事件。所以要取消当前的计时,重新开始计时
timer = setTimeout(fn, delay)
} else { // 进入该分支说明当前并没有在计时,那么就开始一个计时
timer = setTimeout(fn, delay)
}
}
}
// 处理函数
function handle() {
console.log(Math.random())
}
window.addEventListener('scroll', debounce(handle, 500))
应用场景
- 搜索框搜索输入。只需用户最后一次输入完,再发送请求;
- 用户名、手机号、邮箱输入验证;
- 浏览器窗口大小改变后,只需窗口调整完后,再执行 resize 事件中的代码,防止重复渲染。
2.2 节流
主要有两种实现方法:定时器和时间戳。接下来分别用两种方法实现throttle~
定时器版本:
// 节流函数
function throttle(fn, delay) {
let flag = true;
return function () {
if (!flag) {
return false; // 休息,暂不接客
}
// 工作时间
flag = false;
setTimeout(() => {
fn.apply(this, arguments);
flag = true;
}, delay)
}
}
// 处理函数-定时器
function handle() {
console.log(Math.random())
}
function getMathRandom () {
throttle(handle, 1000)();
}
时间戳版本:
function throttle(func, wait) {
let previous = 0;
return function() {
let now = Date.now();
if (now - previous > wait) {
func.apply(this, arguments);
previous = now;
}
}
}
应用场景:
- 按钮点击事件,防止用户多次提交。(loading->flag->节流)
- 拖拽事件
- onScol
- 计算鼠标移动的距离(mousemove)