1. 出现问题
防抖/节流使用无效,(例如防抖,按钮点击多次依旧执行多次)
----> 查看是闭包无效,定义的局部变量依旧为初值
----> 没有相应清除定时器
<el-button @click="btn1">按 钮1</el-button>
<el-button @click="debounce(btn2)">按 钮2</el-button>
</template>
<script setup lang="ts">
// 以下方法调用不生效
const btn1 = () => {
debounce(() => {
console.log('点击了')
}, 1000)()
}
const btn2 = () => {
console.log('点击了');
}
</script>
2. 问题原因
直接调用了防抖函数
原因:这个和vue的事件绑定原理有关。如果直接在函数体内部使用的话,结果就是,一个匿名的立即执行函数来进行执行。由于每次触发点击事件都会返回一个新的匿名函数, 就会生成一个新的函数执行期上下文(称之为执行栈),所以就会防抖/节流就会失效
3. 解决办法
<template>
<el-button @click="btn">按 钮1</el-button>
</template>
<script setup lang="ts">
const btn = debounce(function() {
console.log('点击了');
},500)
</script>
4. 防抖节流函数
type DebouncedFn<T extends (...args: any[]) => any> = (this: ThisParameterType<T>, ...args: Parameters<T>) => void;
type ThrottledFn<T extends (...args: any[]) => any> = (this: ThisParameterType<T>, ...args: Parameters<T>) => void;
function debounce<T extends (...args: any[]) => any>(fn: T, delay: number, immediate = false): DebouncedFn<T> {
let timer: number | null = null;
return function(this: ThisParameterType<T>, ...args: Parameters<T>) {
// if (timer !== null) clearTimeout(timer);
timer && clearTimeout(timer)
if (immediate) {
const callNow = !timer;
timer = setTimeout(() => {
timer = null;
}, delay);
callNow && fn.apply(this, args);
} else {
timer = setTimeout(() => {
fn.apply(this, args);
}, delay);
}
};
}
function throttle<T extends (...args: any[]) => any>(fn: T, delay: number, immediate = false): ThrottledFn<T> {
let lastCall = 0;
return function(this: ThisParameterType<T>, ...args: Parameters<T>) {
const now = new Date().getTime();
// immediate 不为 true 时, 不立即执行
lastCall === 0 && !immediate && (lastCall = now)
const diff = now - lastCall;
if (diff >= delay) {
lastCall = now;
fn.apply(this, args);
}
};
}
export {
debounce,
throttle
}
到此这篇关于vue中使用闭包(防抖和节流)失效问题的文章就介绍到这了,更多相关vue 闭包失效内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!