通俗来说
防抖和节流就是限制方法的执行次数。为什么?作者来举一个小例子。
防抖
通过 setTimeout,将一定时间内的多次触发变成一次触发。
例:
// 获取一个id为 btn 的按钮元素, html 代码省略
const btn = document.getElementById('btn')
btn.addEventListener('click', submit)
function submit () {
console.log('hello')
}
想一想,你平时在网页上是否有短时间内多次点击同一元素?大多数人都是有的吧,就拿上述代码来说,如果用户短时间内多次点击按钮,就会让sumbit 方法执行执行多次,十分影响性能和用户体验。
这样解决:
btn.addEventListener('click', debounce(submit))
// 我们可以用 setTimeout
function debounce(fun, delay) {
// 定时器
let timeout;
return function () {
// 清除之前的定时器
clearTimeout(timeout)
timeout = setTimeout(() => {
fun.apply(this, arguments)
}, delay)
}
}
但是这种方法也是有问题的,就是第一次的点击有明显的延迟,极大的影响了用户的体验。所以,我们可以封装一下:
// debounce 第三个参数: 用户第一次点击不延迟
btn.addEventListener('click', debounce(submit, 1000, true))
// 我们可以用 setTimeout
function debounce(fun, delay, allow) {
// 定时器
let timeout;
return function () {
if (timeout) {
clearTimeout(clear)
timeout = null
}
if (allow) {
fun.apply(this, arguments)
} else {
timeout = setTimeout(() => {
fun.apply(this, arguments)
}, delay)
}
}
}
节流
节流就是一定时间内只触发一次方法。
有些代码就省略了:
btn.addEventListener('click', throttle(sumbit, 500, 1000))
// waitTime : 触发点击事件后,500ms 后运行 submit 方法
// mustRunTime ; 至少相隔 1000ms ,触发点击事件后,直接运行 submit 方法
function throttle(fun, waitTime, mustRunTime) {
let timeout
let startTime = new Date()
return function () {
let endTime = new Date()
clearTimeout(timeout)
timeout = null
if (endTime - startTime > mustRunTime) {
fun.apply(this, arguments)
startTime = endTime
} else {
timeout = setTimeout(fun, waitTime)
}
}
}
作者水平有限,如有错误,欢迎指出。谢谢~