参考资料
前言
抖动和防抖都是用来限制函数的执行频率,以优化函数触发频率过高导致的响应速度更不上触发速度,出现延迟、假死或卡顿的现象。
常见的频繁触发的事件有:
- 输入框的keyup/keydown
- 调整窗口大小的resize
- 页面滚动的scroll
- 鼠标滑动的mousedown/mousemove
防抖
在高频事件触发后,n秒后执行函数。如果n秒内高频事件再次被触发,则重新计时。
防抖适合在搜索框中应用,即用户输入完后停顿一段时间才发送网络请求。
function debounce(func, delay = 1000) {
let timeout
return function () {
clearTimeout(timeout)
timeout = setTimeout(() => { // 注意,这里使用的是箭头函数,因此下面的this指向的是被监听的dom元素,而不是window
func.apply(this, arguments)
}, delay)
}
}
const searchInput = document.getElementById('searchInput')
searchInput.addEventListener('keyup', debounce(function (e) {
console.log('\n执行查询代码');
console.log(this);
console.log(e)
}))
更高级的功能就不实现了,比如第一次立即执行,等到n秒后才能重新触发,或者取消防抖等,详细见参考资料1。
节流
在高频事件触发后,立即执行函数。如果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)
}
}
loadash
loadash是一个js的第三方库,其提供了防抖和节流的函数,我们可以用loadash来加快开发效率。
1)模拟用户操作
let index = 0 // 该变量代表用户的输入值
const intervalId = setInterval(function () {
index++ // 用户输入值加一
test(index) // 调用test,将用户输入值传入
if (index === 10) {
// index到10时模拟结束
clearInterval(intervalId)
}
}, 300)
2)测试debounce
// 生成一个debounce函数,只有用户无操作1000毫秒后才会执行传入的函数
const test = _.debounce(function (value) {
console.log(value)
}, 1000)
输出:
10
3)测试throttle
// 生成一个throttle函数,每隔1000毫秒允许执行传入的函数
const test = _.throttle(function (value) {
console.log(value)
}, 1000)
输出:
1
4
8
10