vue 中的 method 实现函数防抖的坑
函数防抖是当函数在重复触发时, 只执行一次. 以此减少不必要的执行, 优化体验. lodash提供了 debounce 和 throttle 方法, 分别用于实现函数的防抖和节流. 在最近维护的一个内开源vue项目中. 发现大量的节流用法是错误的. 因此记录下正确的用法.
错误演示1
在线演示: codesandbox.io/s/vue-metho…
原来使用如下的写法. 当页面上引用多个该组件的时候, 发现同时点击这些按钮后. 有些组件在点击后未能触发节流函数.
<template>
<h1>vue 方法的节流的错误用法1</h1>
<button @click="clickDebounce">click</button>
</template>
<script>
import { debounce } from 'lodash'
export default {
name: "App",
methods: {
clickDebounce: debounce(function () {
console.log('click')
}, 1000),
}
};
</script>
该写法的问题在于, 在组件被引入的时候生成了一个节流函数, 每个组件实例化之后的 clickDebounce 方法都指向了同一个节流函数. 因此当同时引入多个该组件的时候, 会同时调用同一个节流函数. 导致有些组件的方法未能触发
错误演示2
在线演示: codesandbox.io/s/vue-metho…
<template>
<h1>vue 方法的节流的错误用法2</h1>
<button @click="clickDebounce">click</button>
</template>
<script>
import { debounce } from 'lodash'
export default {
name: "App",
props: {
compId: String
},
methods: {
clickDebounce(){
const fn = debounce(function () {
console.log('click')
}, 1000)
fn()
}
}
};
</script>
该写法的问题在于, vue 方法每次调用时都会生成一个新的节流函数, 1000ms 以后触发console. 因此无法实现节流的效果
正确的写法
在线演示: codesandbox.io/s/vue-metho…
比较简单的正确用法, 就是自己通过 setTimeout 实现一个节流函数.
<template>
<h1>实现 vue 方法的节流(正确用法)</h1>
<button @click="clickDebounce">click</button>
</template>
<script>
export default {
name: "Right",
methods: {
clickDebounce() {
clearTimeout(this.timer)
this.timer = setTimeout(() => {
console.log('click')
}, 1000)
}
}
};
</script>