概叙:
开发中,经常会遇到以下场景:监听鼠标移动 onmousemove,监听页面滚动 onscroll,监听大小变化 onresize,监听 input 输入,按钮的搜索、提交功能等。这些场景下,事件会被频繁触发,但我们并不想事件被频繁触发,这时就需要通过防抖和节流来限制频繁操作。
防抖和节流都是为了解决事件频繁触发的问题,但在实现原理上有些不同,具体实现原理看下文。
一、防抖(debounce)
1、原理:
当持续触发事件时,在一定时间内没有再触发事件,事件才会处理函数一次,如果在设定的时间到来之前,又触发了事件,则重新开启定时器,执行最后一次触发事件。
2、应用场景:
- scroll事件滚动
- 浏览器窗口的缩放resize事件
- 搜索框输入查询的时候
- 表单验证
- 按钮的提交事件
3、代码:
function debounce (fn, delay = 1000) {
let time = null
return function () {
// 获取当前this
let that = this
// 判断是否已经存在,如果存在直接清除
if (time) {
clearTimeout(time)
}
time = setTimeout(() => {
// 使fn 中this,执行当前调用者,并传入参数
fn.apply(that, arguments)
}, delay)
}
}
// 测试demo
function logger(e){
console.log('log -----')
}
btn.addEventListener('click',debounce(logger, 1000))
二、节流(throttle)
1、原理:
在持续触发事件时,在一定时间内只调用一次函数,如果在规定时间内,再次触发此事件,则直接忽略不执行,其主要目的就是减少一段时间的触发频率
2、应用场景:
- DOM元素拖拽功能实现
- 计算鼠标移动距离
- 监听scroll滚动事件
- 搜索、提交等按钮功能
3、代码:
function throttle (fn, delay = 1000) {
let time = null;
return function () {
let that = this;
// 如果已经存在定时器了,则 不做处理
if (!time) {
time = setTimeout(() => {
fn.apply(that, arguments);
// 完结时,将time改为null
time = null;
}, delay);
}
};
}