start
- 总是听到防抖节流,但是一直没有分清楚这两者之间的区别。
- 现在开始学习也不晚,先学习一下防抖
概念
防抖(debounce),防止抖动, 短时间内触发多次,最终只触发一次;
实现防抖
例如我有一个输入框,我希望在我键盘停止输入的 500 毫秒之后,可以自动搜索。
<!DOCTYPE html>
<html lang="en">
<body>
<input type="text" id="in" />
<script>
var input = document.querySelector('#in')
let say = function (e) {
console.log('值改变事件', e.target.value)
}
input.addEventListener('keyup', say)
</script>
</body>
</html>
可以看到在我上面的截图中,我本意是想搜索你好
,但是我的 say 方法,在操作键盘的时候被执行了很多次。(但是我本意只是想,在我停止操作后,执行一次 输出你好)这种时候就可以利用防抖这个概念了。
再重温一下,防抖:短时间内触发多次,最终只触发一次; (当我操作键盘,如果 500 毫秒之内多次触发键盘,及重新计时)
<!DOCTYPE html>
<html lang="en">
<body>
<input type="text" id="in" />
<script>
var input = document.querySelector('#in')
var say = function (e) {
console.log('值改变事件', e.target.value)
}
input.addEventListener('keyup', debounce(say, 500))
function debounce(fn, wait) {
// 1.记录定时器
var timer
console.log(timer, '111')
// 2.它本身需要返回一个方法
return function () {
// 3.清除之前的定时器(这个地方 debounce 只执行一次,然后由于闭包,常驻于内存,所以会一直存储着定时器相关的信息。)
clearTimeout(timer)
var that = this
var arr = arguments
timer = setTimeout(function () {
fn.apply(that, arr)
}, wait)
}
}
</script>
</body>
</html>
如果想首次已进入就执行,间隔一段时间后才可以执行?
<!DOCTYPE html>
<html lang="en">
<body>
<input type="text" id="in" />
<script>
var input = document.querySelector('#in')
var say = function (e) {
console.log('值改变事件', e.target.value)
}
input.addEventListener('keydown', debounce(say, 500, { immediate: true }))
function debounce(fn, wait, option) {
var timer
return function () {
if (timer) {
clearTimeout(timer)
}
var that = this
var arr = arguments
if (option && option.immediate) {
var isRun = !timer
timer = setTimeout(function () {
console.log(timer)
timer = null
}, wait)
if (isRun) fn.apply(that, arr)
} else {
timer = setTimeout(function () {
fn.apply(that, arr)
}, wait)
}
}
}
</script>
</body>
</html>
个人总结:
- 防抖:一段时间内不管你触发多少次,我只触发一次;
- 举一个别人说的比较好的例子,防抖就类似于我们手机设置了10分钟息屏,当我们操作了手机,手机的息屏计时就重新计算,直到我们真的没有操作手机达到10分钟,手机才会真正息屏。
- 手写的过程中遇到的问题:
timer
这个变量如何实现一直记录着前一个定时器返回值。debounce 只执行一次,timer
由于闭包,常驻于内存;- 切记要存储定时器的返回值;
- 首次进入执行这个逻辑,稍微有点绕。这个地方很巧妙,当
!timer
为 true , 才会执行真正的回调;简单总结一下就是:我首次进来就触发,必须等我这个定时器执行完毕,才可再次触发(定时器中的timer=null就是这个意思)。