防抖是将多次执行变为最后一次执行
节流是将多次执行变成每隔一段时间执行
什么是防抖节流:
防抖(debounce):当持续触发事件时,一定时间段内没有再触发事件,事件处理函数才会执行一次,如果设定的时间到来之前,又一次触发了事件,就重新开始延时。
节流(throttle):当持续触发事件时,保证一定时间段内只调用一次事件处理函数。
防抖
在第一次触发事件时,不立即执行函数,而是给出一个期限值比如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) //说明当前并没有在计时,那么就开始一个计时
}
}
}
节流
在高频事件触发后,立即执行函数。如果n秒内高频事件再次被触发,则拒绝执行函数。
防抖适合在下拉无限加载页面场合应用,不必等到用户停下来才发起网络请求。
function throttle(func, delay = 1000) {
let canRun = true // 用闭包维护一个变量
return function () {
if (canRun === false) return
canRun = false
setTimeout(() => {
func.apply(this, arguments)
canRun = true
}, delay)
}
}
防抖节流的使用场景
防抖(debounce)
1.search搜索联想,用户在不断输入值时,用防抖来节约请求资源。(input框)
2.window触发resize的时候,不断的调整浏览器窗口大小会不断的触发这个事件,用防抖来让其只触发一次
节流(throttle)
1.鼠标不断点击触发,mousedown(单位时间内只触发一次) (点击事件)
2.监听滚动事件,比如是否滑到底部自动加载更多,用throttle来判断
第三方库实现
事实上我们可以通过一些第三方库来实现防抖操作:
- lodash
- underscore
我们这里以lodash为例,我们可以理解成lodash是underscore的升级版
安装lodash
lodash的官方:Lodash 简介 | Lodash 中文文档 | Lodash 中文网
lodash的安装有很多种方式:
- 下载lodash,本地引入;
- 通过CDN直接引入;
- 通过包管理工具(npm)管理安装;
使用lodash
下面我们通过lodash中的debounce函数对searchChange函数进行处理:
- debounce函数要求我们传入一个需要处理的函数,并且传入一个delay的时间
- 在delay的时间内没有再次触发事件,才会真正执行函数
- debounce返回一个新的函数,将新的函数设置到oninput事件中
// 对searchChange处理
var _search= _.debounce(searchChange, 500);
// 绑定oninput
search.oninput = _search