知识篇 -- JS 节流和防抖
# 节流和防抖
节流和防抖在浏览器性能的优化手段中非常常见,像一些鼠标重复点击、页面滚动、鼠标拖拽、Input框自动填充以及文档编辑保存等场景。 虽然都是防止事件的重复发生,但是它们还是有一些区别。
本篇文章主要是记录节流防抖的实现以及如何区分使用节流还是使用防抖,已防自己在开发的过程当中被领导骂个狗血喷头。
# 防抖(deounce)
- 定义
等一个有效指令: 给一个固定时间,如果你开始触发动作,并且在这个固定时间内不再有任何动作,我就执行一次,否则我每次都会重新开始计时。
- 实现
/**
* @description: Add by RayShine
* @param {Fn} func
* @param {int} delay
* @return {*}
*/
deounce (func, delay = 200) {
let timer = null
return function () {
// 清除上次还未发生的事件
timer && clearTimeout(timer)
// 设置一个新的定时器
timer = setTimeout(func, delay)
}
}
使用场景
- 登录、提交或短信验证时,避免用户重复点击
- Input框自动填充,避免服务器压力过大
- 窗口自适应,避免渲染时闪屏
- 文档编辑时实时保存,避免更改次数过多
# 节流(throttle)
- 定义
按时执行一个有效指令: 用户会反复触发一些操作,比如鼠标移动事件,此时只需要指定一个“巡视”的间隔时间,不管用户期间触发多少次,只会在间隔点上执行给定的回调函数。
- 实现
/**
* @description: Add by RayShine
* @param {Fn} func
* @param {int} delay
* @return {*}
*/
throttle (func, delay = 200) {
let timer = null
// 开始时间
let startTime = Date.now()
return function () {
// 触发时间
const curTime = Date.now()
// 计算上次事件到本次事件的时间间隔点
const remaining = delay - (curTime - startTime)
const context = this
const args = arguments
// 清除上次还未发生的事件
timer && clearTimeout(timer)
// 如果到了delay间隔时间,执行一次回调函数,并重新计时
if (remaining <= 0) {
func.apply(context, args)
startTime = curTime
// 如果没到delay间隔时间,设置一个定时器,保证事件不再发生时能最终执行一次
} else {
timer = setTimeout(func, remaining)
}
}
}
使用场景
- 鼠标滚动事件,避免触发次数过多,页面过渡不够平滑,影响用户体验。(例如本站的导航栏,向下滚动时隐藏,向上滚动时显示,如触发次数过多,emmmm~,可以想象得到。)
- Input框自动填充,避免服务器压力过大
- 下拉加载时,避免服务器压力过大
- 拖拽动画,避免计算次数过多,影响浏览器性能
# 关于节流和防抖的区别与联系
联系
- 都是利用 闭包 的优点,通过私有化变量来实现的。
- 都是用于应用的性能优化
- 都是用来抑制事件的重复执行
区别
防抖是为了事件最终只执行一次,避免浏览器认为是多次事件。
节流是为了控制事件执行的速率,即每隔多长事件执行一次。