Vue3+Nuxt3中Element Plus子组件emit事件防抖失效求助
Vue3+Nuxt3中Element Plus el-input子组件emit事件防抖失效的解决方法
问题核心原因
你的代码存在三个关键问题导致防抖失效:
- 防抖函数实现错误:原函数未清除旧定时器,每次输入都会新增独立定时器,无法实现"延迟执行最后一次操作"的防抖效果;同时未传递事件参数,回调无法获取输入值。
- 未正确绑定防抖逻辑:子组件中
debounceInput直接触发emit,没有用防抖函数包裹处理。 - 响应式参数与ref更新错误:
debounceprops变化时防抖函数不会自动更新,且父组件中直接给ref变量赋值而非修改.value属性,导致响应式失效。
解决方案
步骤1:修复防抖函数
修改防抖函数,添加定时器清除逻辑并支持参数传递:
export const debounce = (callback: Function, delayTime: number) => { let timeoutId: NodeJS.Timeout | null = null; return (...args: any[]) => { // 清除上一次未执行的定时器 if (timeoutId) clearTimeout(timeoutId); timeoutId = setTimeout(() => { callback(...args); // 传递调用时的参数 }, delayTime); }; };
步骤2:子组件实现响应式防抖逻辑
使用computed根据debounce props动态生成防抖函数,确保延迟时间变化时自动更新:
<!-- input 子组件 --> <script lang="ts" setup> import { debounce } from '@/utils/debounce'; // 替换为你的防抖函数实际路径 import { computed } from 'vue'; interface Props { modelValue?: string; placeholder?: string; type: string; debounce: number; } const props = withDefaults(defineProps<Props>(), { modelValue: '', placeholder: 'Please input', type: 'text', debounce: 0 }); const emit = defineEmits(['update:modelValue']); // 根据debounce参数动态生成防抖函数,debounce为0时直接执行 const debouncedEmit = computed(() => { if (props.debounce === 0) { return (value: string) => emit('update:modelValue', value); } return debounce((value: string) => { emit('update:modelValue', value); }, props.debounce); }); const handleInput = (e: Event) => { const inputValue = (e.target as HTMLInputElement).value; debouncedEmit.value(inputValue); }; </script> <template> <el-input v-bind="$attrs" :model-value="modelValue" :placeholder="placeholder" :type="type" class="base-input" :class="{ search: type === 'search' }" @input="handleInput" > <template #suffix> <el-icon> <img v-if="type === 'search'" class="w-[18px] h-[18px] mx-auto cursor-pointer" src="images/search.svg" alt="logo" /> </el-icon> </template> </el-input> </template>
步骤3:修复父组件的ref更新逻辑
父组件中search是ref对象,必须通过.value属性更新值:
<!-- Custom Input 父组件 --> <script lang="ts" setup> const search = ref(''); </script> <template> <CustomInput :model-value="search" placeholder="Search" type="search" class="w-full md:max-w-[330px]" :debounce="500" @update:modelValue="(newValue: string) => (search.value = newValue)" /> </template>
内容的提问来源于stack exchange,提问作者M12H
相关产品推荐
相关产品推荐

