防抖
思路: 在第一次触发事件时,不立即执行函数,而是给出一个期限值比如200ms
- 如果在200ms内没有再次触发滚动事件,那么就执行函数。
- 如果在200ms内再次触发滚动事件,那么当前击时取消,重新开始计时。
效果: 如果短时间内触发同一个事件,只会执行一次函数
实现: 既然前面都提到了计时,实现的关键是setTimeout
这个函数,由于需要变量保存计时,考虑维护全局纯净,可以借助闭包
来实现
function debounce(fn,delay) {
let timer = null;
return function() {
if(timer) {
clearTimeout(timer);
timer = setTimeout(fn,delay);
}else {
timer = setTimeout(fn,delay);
}
}
}
const test = debounce(() => {
console.log(234)
}, 400)
注意
防抖定义: 对于短时间内连续触发的事件,防抖的目的就是让某一个时间期限内,事件只触发一次。
节流
根据上面介绍的防抖效果来看
- 只要不断连续的触发改事件,理论上是不会执行回调函数的。
如果产品需求期望处理方案:当不断连续触发改事件,希望在某一个时间间隔后可以触发回调函数?
原理很简单:就像一个类似控制的阀门,我们只需要控制在时间间隔后开启关闭。
效果: 如果短时间内触发一个事件,那么在执行回调函数完毕后,那么回调函数在指定时间内是不能触发的,直到过了这个时间段才可以触发.
实现: 这里借助setTimeout
实现,需要保存一个变量状态valid表示是否处于工作状态
function throttle(fn, delay) {
let valid = true//有效的
return function() {
if(!valid) {
return false
}else {
//工作完后变为 无效
valid = false
//在一定的时间段变为工作状态
setTimeout(() => {
fn();
valid = true;
}, delay)
}
}
}
注意
节流定义:对于短时间内触发事件,节流目的想让触发回调函数的频率降低,在某一时间内回调函数是失效状态。
应用场景
- 当用户input事件,例如需要实时监听到输入框的变化,但是要降低触发回调函数的频率,通过throttle节流从而达到优化目的。
- 页面的resize事件,常见于需要做页面适配的时候,需要监听到最后一次页面尺寸大小。
代码优化
上述内容主要是介绍debounce和throttle核心思路实现,并代表实际的库。需要借助上下文环境和argument(this指向)。
function debounce (fn,wait) {
let timer = null;
return function () {
if(timer) { clearTimeout(timer) }
let _this = this;//保存当前this
let args = arguments;
timer = setTimeout(function() {
fn.apply(_this, args)
},wait);
}
}
function throttle (fn,wait) {
let previous = 0;
return function() {
let _this = this;
let args = arguments;
let now = new Date().getTime()//时间戳
if(now - previous > wait) {
fn.apply(_this, args);
previous = now
}
}
}
网友评论