发布于 2021-11-20
如何在 vue 中使用 Debounce、Throttle
vuejavascript
如input、resize、scroll、intersection observer 等事件可能发生得非常频繁,例如每秒发生几次,因此调用一个动作,比如对每个事件发出读取请求,并不是一个明智的方法。
为什么要使用 debounce 和 throttle
防抖和节流就是针对响应跟不上触发频率这类问题的两种解决方案。在给 DOM 绑定事件时,有些事件我们是无法控制触发频率的。 如鼠标移动事件 onmousemove, 滚动滚动条事件 onscroll,窗口大小改变事件 onresize,瞬间的操作都会导致这些事件会被高频触发。 如果事件的回调函数较为复杂,就会导致响应跟不上触发,出现页面卡顿,假死现象。 在实时检查输入时,如果我们绑定 onkeyup 事件发请求去服务端检查,用户输入过程中,事件的触发频率也会很高,会导致大量的请求发出,响应速度会大大跟不上触发。
在 watcher 中使用 debounce
- 在
created生命周期将this.debounce绑定到this上,这样this.debounce就可以在created生命周期中使用。 - 在
watch函数中,使用this.debounce调用debounce函数,并传入this.debounce的回调函数。 - 在事件销毁前,使用
this.debounce调用clear函数,清除定时器。
<template>
<input v-model="value" type="text" />
<p>{{ value }}</p>
</template>
<script>
import debounce from 'lodash.debounce'
export default {
data() {
return {
value: ''
}
},
watch: {
value(...args) {
this.debouncedWatch(...args)
}
},
created() {
this.debouncedWatch = debounce((newValue, oldValue) => {
console.log('New value:', newValue)
}, 500)
},
beforeUnmount() {
this.debouncedWatch.cancel()
}
}
</script>使用 debounce 处理事件
<template>
<input v-on:input="debouncedHandler" type="text" />
</template>
<script>
import debounce from 'lodash.debounce'
export default {
created() {
this.debouncedHandler = debounce((event) => {
console.log('New value:', event.target.value)
}, 500)
},
beforeUnmount() {
this.debouncedHandler.cancel()
}
}
</script>为什么不适用debounce或throttle直接绑定函数呢?比如:
<template>
<input v-on:input="debouncedHandler" type="text" />
</template>
<script>
import debounce from 'lodash.debounce'
export default {
methods: {
// Don't do this!
debouncedHandler: debounce(function (event) {
console.log('New value:', event.target.value)
}, 500)
}
}
</script>使用export default { ... }从组件导出的 options 对象,包括方法,将被组件的所有实例重用。如果网页中有 2 个或更多的组件实例,那么所有的组件都将使用相同的debounce或throttle的函数方法。
总结
在 vue 中使用 debounce 和 throttle 函数,应该在 created 和 beforeUnmount 生命周期中使用,而不是在 watch 中使用。
<template>
<input v-on:input="debouncedHandler" type="text" />
</template>
<script>
export default {
created() {
this.debouncedCallback = debounce((...args) => {
// The debounced
callback
}, 500)
},
watch: {
value(...args) {
this.debouncedCallback(...args)
}
}
}
</script>