防抖 & 节流 笔记
参考博文注释很详细到位
防抖 (debounce)
对于短时间内连续触发的事件,
防抖的含义就是让某个时间期限内,
事件处理函数只执行一次。
在第一次触发事件时,不立即执行函数,而是给出一个期限值(延迟执行)
/*
* fn [function] 需要防抖的函数
* delay [number] 毫秒,防抖期限值
*/
function debounce(fn, delay) {
let timer = null; // 借助闭包
return function() {
if (timer) {
// 进入该分支语句,说明当前正在一个计时过程中,
// 并且又触发了相同事件。所以要取消当前的计时,
// 重新开始计时
clearTimeout(timer);
}
// 当前没有在计时,开始一个计时
timer = setTimeout(fn, delay);
}
}
// 监听浏览器滚动事件,返回当前滚动条与顶部的距离
function showTop() {
let scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
console.log('滚动条位置:' + scrollTop);
}
// delay 根据实际需要来配置
window.onscroll = debounce(showTop, 1000)
节流 (throttle)
如果在限定时间段内,不断触发滚动事件
(比如某个用户闲着无聊,按住滚动不断的拖来拖去),
只要不停止触发,理论上就永远不会输出当前距离顶部的距离。
? 即使用户不断拖动滚动条,也能在某个时间间隔之后给出反馈
设计一种类似控制阀门一样定期开放的函数,
也就是让函数执行一次后,在某个时间段内暂时失效,
过了这段时间后再重新激活(类似于技能冷却时间
)
function throttle(fn, delay) {
let valid = true;
return function () {
if (!valid) {
// 休息时间 暂不接客
// 技能冷却中
return false;
}
// 工作时间,执行函数并且在间隔期内把状态位设为无效
valid = false;
// * 可以把状态位换成时间戳
// 利用时间戳差值是否大于指定间隔时间来做判定。
// * 可以直接将setTimeout的返回的标记当作判断条件
// 判断当前定时器是否存在,
// 如果存在表示还在冷却,并且在执行fn之后消除定时器表示激活
setTimeout(() => {
fn()
valid = true;
}, delay);
}
}
// 监听浏览器滚动事件,返回当前滚动条与顶部的距离
// 如果一直拖动滚动条进行滚动,那么会以1s的时间间隔,
// 持续输出当前位置和顶部的距离
function showTop() {
let scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
console.log('滚动条位置:' + scrollTop);
}
window.onscroll = throttle(showTop, 1000);
other
-
搜索框input事件
例如要支持输入实时搜索可以使用节流方案(间隔一段时间就必须查询相关内容)
或者实现输入间隔大于某个值(如500ms),就当作用户输入完成,然后开始搜索,
具体使用哪种方案要看业务需求. -
页面resize事件
常见于需要做页面适配的时候。
需要根据最终呈现的页面情况进行dom渲染
(这种情形一般是使用防抖,因为只需要判断最后一次的变化情况) -
实际还要考虑
作用域
参数传递
argument
以及上下文环境apply