事件稀释:有些事件在一段时间内会多次触发,事件稀释就是减少这些事件绑定的处理函数的执行频率,以减少频繁的事件处理对性能的损耗。事件稀释有两种方式:防抖和节流。
可直接使用的第三方库有:underscore、lodash 等。
例如:input 框的输入事件,不停地输入就会不停地执行绑定的事件处理函数。
<input id='input'>
const input = document.getElementById('input')
input.oninput = function(event) {
console.log('发送网络请求:' + this.value, event)
}
防抖:
防抖:当事件被触发时,处理函数并不会立即执行,而是会等待一定的时间。如果在这段时间内事件没有再次被触发,就执行处理函数;如果在这段时间内,事件又被触发了,则重新开始等待。
多次触发,只生效最后一次。适用于多次触发只需要生效一次的场景。
代码实现:
实现思路:事件被触发,开启一个定时器 --> 在给定的时间内,如果事件再次被触发,则清除上一次的定时器,重新设置一个定时器 --> 直到事件不再触发,最后一次设置的定时器不会再被清除了,延时时间到,执行代码逻辑
。
// 定义防抖函数:接收两个参数:绑定的处理函数和要延迟的时间,返回一个事件触发时真正要执行的已经有防抖功能的处理函数
function debounce(fn, delay) {
// 1. 记录上一次事件触发的定时器。_debounceFn 函数引用了外部的 timer,形成了一个闭包,因此,timer 在内存中会被保存下来
let timer = null
const _debounceFn = function() {
// 2. 每次触发都清除上一次的定时器
if (timer) clearTimeout(timer)
// 3. 然后重新设置定时器。直到超过了给定的时间,还是没有再次触发,最后一次设置的定时器中的代码逻辑执行
timer = setTimeout(() => {
fn.call(this, ...arguments) // 给处理函数绑定正确的 this 和传参
timer = null
}, 1000)
}
return _debounceFn
}
// 使用防抖函数
const input = document.getElementById('input')
input.oninput = debounce(function(event) {
console.log('发送网络请求:' + this.value, event)
}, 1000)
在 1 秒钟内重复触发输入事件,不执行绑定的处理函数,直到超过了 1 秒钟,才执行绑定的处理函数。
节流:
节流:在一定的时间间隔内,不管触发多少次事件,处理函数只执行一次。
每隔一段时间生效一次。适用于多次触发需要生效多次的场景。
代码实现:
// 定义节流函数:接收两个参数:绑定的处理函数和时间间隔,返回一个事件触发时真正要执行的已经有节流功能的处理函数
function throttle(fn, duration) {
// 1. 上一次处理函数执行的时间戳。_throttleFn 函数引用了外部的 lastTime,形成了一个闭包,因此,lastTime 在内存中会被保存下来
let lastTime = 0
const _throttleFn = function() {
// 2. 当前处理函数执行的时间戳
const currTime = new Date().getTime()
// 3. 判断当前处理函数执行的时间戳距离上一次处理函数执行的时间戳是否超过了 duration 设定的时间间隔。如果没超过,遵循不管触发了多少次事件,在一定的时间间隔内只执行一次处理函数的原则,什么也不做;如果超过了,就执行函数
if (currTime - lastTime >= duration) {
fn.call(this, ...arguments) // // 给处理函数绑定正确的 this 和传参
// 4. 更新处理函数执行的时间戳
lastTime = currTime
}
}
return _throttleFn
}
// 使用节流函数
const input = document.getElementById('input')
input.oninput = throttle(function(event) {
console.log('发送网络请求:' + this.value, event)
}, 1000)
一直输入,每隔 1 秒钟会触发一次绑定的处理函数。