Vue3中debounce方法传入的回调函数无法执行问题排查
问题分析与解决
核心问题:防抖函数的调用方式错误
你之前的问题出在没有正确调用防抖函数返回的包装函数:
- 防抖函数(
debounce)的作用是生成一个带有防抖逻辑的新函数,你需要把这个新函数保存下来,在事件触发时调用它; - 你最初在
onMounted里直接执行debounce(() => console.log('hello'), 500),只是生成了防抖函数,但从未调用这个返回的函数,所以回调自然不会执行。
实际场景的错误与修正
在keyup事件的handleTagKeyUp中,最初的写法是把防抖逻辑直接嵌在事件处理函数里,这会导致每次keyup都重新创建一个新的防抖函数,完全起不到防抖效果。
错误写法的问题
每次触发keyup,都会执行debounce(...)生成新的防抖函数,之前的定时器会被丢弃,根本无法累积等待时间,防抖失效。
正确写法的逻辑
把需要防抖执行的逻辑抽成独立函数findTags,并将debounce返回的包装函数赋值给它。这样每次keyup触发时,调用的都是同一个防抖包装函数,定时器会被正确地清除和重置,实现预期的防抖效果:
const handleTagKeyUp = (event: KeyboardEvent): void => { filteredTags.value = []; const value = inputTags.value.trim(); if (event.code === 'Enter') { addTag(value); return; } if (value.length < 3) { return; } // 调用同一个防抖包装函数 findTags(value); }; // 提前生成防抖函数并保存 const findTags = debounce((value: string) => { const selectedTagNames = selectedTags.value.map((t: Tag) => t.name.toLowerCase()); filteredTags.value = props.tags.filter((t: Tag) => t.name.toLowerCase().includes(value) && ! selectedTagNames.includes(t.name.toLowerCase())); }, 500);
额外提示:自定义防抖函数的this指向
你的自定义防抖函数里用了fn.apply(this, args),在Vue3的setup语法糖中,this是undefined的,不过因为你后来的回调是箭头函数(不绑定this),所以没影响。如果需要处理普通函数的this,可以改成:
const debounce = (fn: Function, delay: number): Function => { let timeout: NodeJS.Timeout; return function(...args: any): void { clearTimeout(timeout); timeout = setTimeout(() => { fn.apply(this, args); }, delay); }; };
这里把返回的函数改成普通函数,这样调用时的this会正确绑定到调用上下文。
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

