防抖(debounce)所谓防抖,就是指触发事件后在 n 秒内函数只能执行一次,如果在 n 秒内又触发了事件,则会重新计算函数执行时间,函数执行时一定是用户的最后一次操作之后。
常用于搜索框获取用户输入功能上。
// 防抖:用户重复某一操作 程序只对最后一次操作进行响应,中间的操作会中断定时器
// 类似于回城,回城被打断了就得重新计时
// 应用场景:高频重复的动作只需要执行最后一次 比如搜索框最后一个字打完100ms后再进行搜索联想
let input = document.querySelector("input");
function handle_input() {
console.log(input.value);
}
// 防抖函数 只执行了一次 后面触发input事件执行的函数是匿名函数
function debounce(fn, wait_time) {
let timer = null;
// 闭包保证持有timer变量
return function () {
// 如果已经有一个定时器了,那么就删除这个定时器
if (timer) {
console.log("已存在定时器");
clearTimeout(timer);
}
// 然后新建一个定时器
// 注意:不要写在else里面 因为timer被清除之后不是null而是该定时器的id,是一个数字
timer = setTimeout(fn, wait_time);
};
}
input.addEventListener("input", debounce(handle_input, 1000));
节流(throttle)所谓节流,就是指连续触发事件,但每隔一段时间只执行一次函数,执行时不一定是用户的最后一次操作。
// 节流:用户短时间内下达了多次重复的操作,节流是每隔一定时间只执行一次用户的指令
// 类似于怪猎出招,不是说鼠标点的快出招就快的,而是一定频率只能出招一次(使出的招式是解除节流限制之后的第一次有效输入)
// 应用场景:限制鼠标经过、滚动条滚动、页面大小缩放、video标签进度时间改变等开销较大的操作 比如说懒加载不用时刻监视滚动事件
// 不能用于搜索框,比如我输入1234567 使用节流的话 只有1、1234才会发送ajax请求 而不是用户最后输入的值
// 思路:使用两个时间戳,只有时间差距大到一定程度时,才执行代码
let div = document.querySelector("div");
let index = 0;
function mouse_mover() {
div.innerHTML = index++;
}
// throttle只执行了一次 触发事件执行的函数是返回的匿名函数
function throttle(fn, wait_time) {
// 声明开始时间
let start_time = 0;
// 利用闭包持有start_time变量
return function () {
let now_time = Date.now();
// 如果时间差比较大,才会执行fn函数
if (now_time - start_time >= wait_time) {
fn();
// 重点:让开始时间变成之前触发的时间
start_time = now_time;
}
// else {
// console.log('忽略此次操作');
// }
};
}
div.addEventListener("mousemove", throttle(mouse_mover, 1000));
节流和防抖最大的区别在于:防抖一定是在用户执行最后一次操作后进行执行的,而节流是每隔一定时间执行1次,不一定在用户操作结束了才执行。
除了手写之外,lodash.js 也内置了节流和防抖的函数。