万万Vue中使用防抖Or节流还有这么多细节
前言
防抖、节流函数
在工作中经常用到,但是在使用的时候,经常都是按照网上CV
就完成了,没去考虑很多细节性的问题,今天就来好好研究一下。
vue中防抖和节流
通常情况下,节流和防抖
都是写成公共的方法
,因此本文都的节流和防抖
,就以公共方法为例。
目前在vue2
中,有两种防抖和节流的使用方法
第一种方法加防抖和节流的方式:
javascript
// 正确使用示例
handleInput: debounce((e) => {
console.log(e);
}, 1000),
// 错误使用示例
handleInput() {
return debounce((() => {
console.log('方法执行了');
}), 1000)();
},
第二种方法加防抖和节流的方式:
这种方法需要在created或者mounted
中去声明一个变量来存储这个方法,然后在下面的方法调用再去使用这个方法
javascript
mounted() {
// 声明方法,利用一个变量存储
this.debounceInput = debounce((e) => {
console.log(e);
}, 3000)
},
// 使用方法
handleInput() {
this.debounceInput();
},
细节
上面我们已经了解了使用的方法,那么接下来就是重头戏了,了解一下这两种写法有什么区别,首先是第一种
首先来运行一下,我在防抖内部加一个console.log语句
javascript
export const debounce = (func, time) => {
let timer = null;
console.log(timer, '防抖函数内部的timer');
return (...args) => {
console.log(args);
if(timer) clearTimeout(timer);
timer = setTimeout(() => {
func.apply(this, args)
}, time)
}
}
然后以正确示例的代码执行一下
javascript
// 正确使用示例
handleInput: debounce((e) => {
console.log(e);
}, 1000),
从动图中我们可以看到
,我刷新后没有执行任何操作(注意没有执行任何操作)
,但是debounce却执行了
,这意味这什么?
这时候我们其实防抖函数
已经把return 函数
赋值给我们handleInput这个方法了
这时候其他我们的代码是这样的形式,这里可能会有误解那么timer这些变量哪里来,其实人家还是在util中执行我只是拿过来方便大家理解
那么从代码中我们就可以看在一开始我们debounce其实就已经把结果返回给我们了
这时候我们每次调用其实就是执行deboucne里return
的内容
这时候timer也不会重复声明所以说,防抖有效
,那么来测试一下
javascript
handleInput: debounce((e) => {
console.log(e, 'debounce回调的方法');
}, 1000),
<el-input v-model="ruleForm.name" @input="handleInput"></el-input>
这里绑定了input事件
,我们应该是重复触发就重新计时,如果计时1秒后没有重新触发就输出console.log
那么我们来看一下这种方法为什么不行
javascript
// 错误使用示例
handleInput() {
return debounce((() => {
console.log(e, 'debounce回到的方法');
}), 1000)();
},
先看执行效果
如图所示造成如果结果的原因就是
,我们每次执行handleInput
都会把debounce内容全部的函数执行一次
,但是我们想到仅仅的debounce内部的return的方法执行
如果红框内所示的内容
,但是我们如果放到方法里直接执行显然是不行的,所以就有了第二种
第二种方法
: 其实第二种方法就是在生命周期中,先把调用一次,存储到变量中然后拿到debounce返回的方法
javascript
mounted() {
this.debounceInput = debounce((e) => {
console.log('debounce回调的方法');
}, 3000)
},
// 使用方法
handleInput() {
this.debounceInput();
},
这里我们看一下效果
可以看到防抖的效果还是有的(我这里设置了3秒后回调)
那么我们来看一下debounceInput里的内容是什么
scss
(...args) => {
// console.log(args);
if (timer) clearTimeout(timer);
timer = setTimeout(() => {
func.apply(undefined, args);
}, time);
}
结果也如我们所料
那么两种方法有什么区别吗?
其实两个区别只有一个第一种在debounce的时候无法访问this
如果说debounce
需要访问当前this
的时候就无法访问,同时time
也是固定的
我将代码改成以下形式
javascript
handleInput: debounce((e) => {
console.log(e, 'debounce回到的方法');
}, this.delay),
运行就报错了,所以如果说需要在debounce中访问this或者当前组件的变量
,推荐使用第二种方法