首先,我们得回忆一下Vue 3的自定义指令的写法。Vue 3中,自定义指令的钩子函数和Vue 2有所不同,
vue2自定义指令的钩子函数
-
bind
:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。 -
inserted
:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。 -
update
:所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新 (详细的钩子函数参数见下)。 -
componentUpdated
:指令所在组件的 VNode 及其子 VNode 全部更新后调用。 -
unbind
:只调用一次,指令与元素解绑时调用。
vue3自定义指令的钩子函数
created(el, binding, vnode)
// 在元素被插入到 DOM 前调用beforeMount(el, binding, vnode)
// 在绑定元素的父组件mounted(el, binding, vnode)
// 及他自己的所有子节点都挂载完成后调用beforeUpdate(el, binding, vnode, prevVnode)
// 绑定元素的父组件更新前调用updated(el, binding, vnode, prevVnode)
// 及他自己的所有子节点都更新后调用 -beforeUnmount(el, binding, vnode)
// 绑定元素的父组件卸载前调用 -unmounted(el, binding, vnode)
// 绑定元素的父组件卸载后调用
现在有beforeMount、mounted、beforeUpdate、updated等,不过常用的可能是mounted和updated。
防抖的目的是让某个函数在连续触发时,只在最后一次触发后的一段时间后执行一次。常见的应用场景比如输入框输入时搜索建议,防止频繁请求接口。
那用户的需求应该是指令可以应用在输入框或者按钮上,当用户频繁操作时,比如输入或者点击,防抖指令能确保处理函数不会过于频繁执行。
首先,我需要确定指令的用法,比如v-debounce,可能需要绑定事件类型和回调函数,或者时间间隔。比如:<input v-debounce:input="onInput" />
,或者更灵活一点,允许指定时间和事件类型,比如v-debounce:300ms="handler"。
然后,自定义指令的结构。在Vue 3中,自定义指令通过directives选项注册,或者全局注册。指令的定义对象包含几个钩子函数,比如mounted和beforeUnmount(可能需要清理定时器)。
在mounted钩子中,需要给元素添加事件监听器,并且在事件触发时执行防抖处理。这里需要创建一个防抖函数,每次事件触发时,清除之前的定时器,重新设置一个新的。
比如,当元素挂载时,绑定input事件,事件处理函数用防抖包装用户传入的方法。同时,在组件卸载前,可能需要移除事件监听器,不过如果使用匿名函数的话,可能无法正确移除,所以可能需要保存防抖函数的引用。
另外,用户可能希望自定义防抖的时间,比如默认300毫秒,但可以传入参数修改。这时候可以通过指令的参数来设置时间,比如v-debounce:500
,或者通过修饰符,或者通过绑定的值传递参数。
比如指令的值可以是一个对象,包含handler和time。或者更简单的方式,指令的参数是延迟时间,值是对应的处理函数。例如v-debounce:500="onInput",这样在指令中可以通过binding.arg获取到500,作为延迟时间,binding.value就是处理函数。
那具体实现的话,可能的结构是:
在mounted钩子中,获取元素,事件类型(默认可能是input事件?或者由用户指定),然后绑定事件。比如,如果指令用在按钮的点击事件,可能需要指定事件类型,所以可能需要指令的参数来指定事件类型,或者通过修饰符。
这时候可能需要更复杂的参数解析。比如v-debounce:click.500="handler",或者使用对象语法。
可能用户希望更灵活,所以需要设计指令的参数结构。例如:
v-debounce:eventname.delay="handler"
或者通过binding的arg和修饰符来获取事件和延迟时间。或者,如果用户传递的是一个对象,包含event、handler、delay等属性,会更灵活,但使用起来可能稍显麻烦。
或者,假设用户使用指令时,元素上已经绑定了某个事件,比如@input,这时候指令可能需要自动处理该事件的防抖?这可能比较复杂,因为指令和事件监听器是分开的。
可能更简单的方式是,指令本身负责绑定事件处理函数,并处理防抖。比如:
<input v-debounce:input="onInput" delay="500" />
或者,通过指令的值传递配置。例如:
const debounceDirective = {
mounted(el, binding) {
const { handler, event = 'input', delay = 300 } = binding.value;
let timeout;
el.addEventListener(event, (...args) => {
clearTimeout(timeout);
timeout = setTimeout(() => {
handler(...args);
}, delay);
});
}
}
这样用户需要传递一个对象给指令,比如v-debounce="{ handler: onInput, event: 'input', delay: 500 }"
,但这样可能不太方便。或者允许不同的参数传递方式。
另一种方式是,指令的参数作为事件类型,修饰符作为延迟时间,或者参数是延迟时间,事件类型通过修饰符指定。不过Vue的修饰符是布尔值,无法传值。所以可能需要参数来指定事件类型,而延迟时间通过value的对象传递。
或者,更灵活的方式是,把事件类型作为指令的参数,延迟时间作为修饰符。但修饰符只能是键,所以可能不行。
可能更合理的做法是,指令的参数是事件类型,比如v-debounce:input
,而延迟时间可以通过值来传递,或者作为修饰符的一部分。例如:
<input v-debounce:input.500="onInput" />
但Vue中修饰符是作为对象的键存储在binding.modifiers中,所以这种情况下,修饰符500会被转换为{bindmodifiers: {'500': true}},但这样处理起来不太方便,因为无法直接获取数值。所以可能参数中的第一个部分作为事件类型,第二个作为延迟时间,但这可能需要解析参数,比如用split之类的。
或者,让用户通过对象传递参数:
v-debounce="{ event: 'input', delay: 500, handler: onInput }"
这样在指令内部可以从binding.value中解构出这些属性。
不过这样在模板中使用可能不够简洁,用户可能需要写较多的代码。
所以可能需要折中的方式。例如,默认的事件类型是input,默认延迟是300ms。用户可以通过指令的参数来指定事件类型,通过修饰符来指定延迟时间,但修饰符的问题是无法传值,只能是true。例如:v-debounce:click.500="handler"
但这样可能无法处理,因为修饰符会被视为字符串,而无法直接提取500作为数值。
所以另一种方式,指令的参数可以接受事件类型,而延迟时间通过value来传递,或者作为单独的选项。
可能更好的方式是将指令的参数作为事件类型,delay作为值中的一个属性,或者将值直接作为处理函数,而delay通过参数传递。例如:v-debounce:input.500="handler"
这里,参数部分可能是input,而500可能作为另一个参数,但Vue的指令参数只能是一个单一的字符串,无法通过点号分隔。所以可能需要用另一种方式解析参数,比如用下划线或者分号分隔,例如v-debounce:input_500,然后在指令中分割参数。
不过这可能不够直观,而且Vue的指令参数语法并不支持这种多参数的情况。所以可能更好的方式是在指令的值中传递一个对象,包含事件类型、延迟时间和处理函数。或者,把处理函数作为指令的值,而其他参数通过arg和修饰符传递。
或许更简单的方式是,将事件类型作为指令的参数,延迟时间作为修饰符,但这样修饰符只能作为键,例如:
v-debounce:input.500ms="handler"
但这样修饰符会是500ms: true,需要从修饰符的键中解析出数值,但这样可能比较复杂。
看来这个问题可能需要简化。假设用户只需要处理input事件,并且可以自定义延迟时间,或者允许事件类型和延迟时间都通过指令的参数传递。
或者,可以这样设计:指令的参数是事件类型,而延迟时间通过value对象传递,或者通过修饰符传值?
可能这里需要参考一些现有的实现,或者寻找一种比较简洁的方式。
比如,在Vue的自定义指令中,可以这样使用:
<input v-debounce:input="500" @input="onInput" />
但这样的话,指令可能需要读取绑定的事件监听器,并将其替换为防抖版本。这可能比较复杂,因为指令和事件监听器是分开的。
或者,另一种方式,指令的作用是包装元素的事件处理函数,并替换为防抖版本。例如:
const debounceDirective = {
mounted(el, binding) {
const event = binding.arg || 'input'; // 事件类型,默认为input
const delay = parseInt(binding.value) || 300; // 延迟时间,默认为300ms
let timeout;
const originalHandler = el._debounceOriginalHandler; // 需要获取原来的处理函数?这可能不可行
// 这里可能需要用户将处理函数作为指令的值传递
const handler = binding.value;
el.addEventListener(event, (...args) => {
clearTimeout(timeout);
timeout = setTimeout(() => {
handler(...args);
}, delay);
});
}
}
这样,用户需要这样使用指令:
<input v-debounce:input="onInput" :delay="500" />
或者,将delay作为指令的参数的一部分,但可能不太方便。或者,用户传递的值是一个函数,而delay作为修饰符或参数。
或者,指令的值可以是一个数组,包含处理函数和delay,例如v-debounce:input="[onInput, 500]",然后在指令内部解构。
不过这样可能不够优雅。或许更好的方式是允许用户通过一个对象配置,例如:
<input v-debounce="{ event: 'input', handler: onInput, delay: 500 }" />
然后在指令中解构这个对象。
但这样在模板中需要写比较多的代码,可能用户更喜欢简洁的方式。
回到最初的问题,用户可能想要一个简单的指令,比如:
这样默认处理input事件,延迟300ms。或者允许用户指定事件和延迟,例如:
点击
这时候,指令的参数是click,修饰符是500,但修饰符会被转换为对象中的键,比如修饰符对象是{500: true},这时候如何处理?或者,将参数解析为事件类型,而延迟时间通过value传递,例如:
<button v-debounce:click="500" @click="onClick">点击
这样,指令的参数是click,值是500,然后在指令中,将事件类型作为参数,延迟时间作为值,处理函数则来自于@click绑定的事件。但这里的问题是如何获取事件处理函数,因为@click是单独的事件监听器,而指令无法直接访问它。因此,这种方法可能不可行。
因此,或许正确的方式是将处理函数作为指令的值传递,并且允许用户通过参数指定事件类型,通过修饰符或值中的属性指定延迟时间。
例如:
默认延迟300ms,或者:
但此时,修饰符是500,但binding.modifiers将包含 {500: true},所以需要从修饰符中提取数值。这时候可能需要遍历修饰符的键,找到数值部分。例如:
const delay = Object.keys(binding.modifiers)[0] || 300;
但如果有多个修饰符,可能需要更复杂的处理,或者用户只能指定一个数值作为修饰符。这可能不太可靠,但可能是一种方式。
或者,将延迟时间作为指令的参数的一部分,比如:
v-debounce:input_500="onInput"
然后在指令中,将参数用下划线分割,第一部分是事件类型,第二部分是延迟时间:
const [event, delay] = binding.arg.split('_');
不过这样在模板中使用可能不够直观,但可行。
但Vue的指令参数不支持这样的解析,需要自己处理。
综合考虑,可能最简单的实现是,指令接受事件类型作为参数,延迟时间作为值,处理函数则通过绑定值传递。例如:
<input v-debounce:input="500" @input="onInput" />
但这样指令的值是延迟时间,而处理函数是@input绑定的,但指令无法直接访问事件处理函数,因为它们是不同的绑定。因此,这种方法可能不可行。
看来正确的做法是将处理函数作为指令的值传递,同时允许配置事件类型和延迟时间。例如:
Click me
然后在指令中解构binding.value:
const { event, handler, delay } = binding.value;
这样用户需要传递一个对象,其中包含事件类型、处理函数和延迟时间。但这样可能需要在模板中写较多的代码,尤其是处理函数可能需要通过一个对象传递,可能不太方便。
或者,可以将事件类型作为参数,处理函数作为值,延迟时间作为另一个参数或者通过修饰符。比如:
Click
但Vue的指令参数只能是一个,所以这种写法可能无法正确解析。比如,参数会是"click:500",需要自己分割。
或者,使用动态参数:
<button v-debounce:[event]="handler" />
但这样动态参数可能不太方便。
看来这个问题可能需要一个折中的方案。假设用户只需要处理input事件,并且可以自定义延迟时间,那么指令可以设计为:
<input v-debounce="500" @input="onInput" />
然后指令的作用是将@input的处理函数包装成防抖的。但如何访问到用户绑定的@input处理函数呢?这可能比较复杂,因为指令无法直接访问元素上的事件监听器,除非在指令中覆盖它。
另一种方法是,指令自己绑定事件处理函数,这样用户不需要再使用@input,而是通过指令的值传递处理函数和配置。例如:
然后在指令内部绑定input事件,并在触发时调用handler,这样用户不需要再写@input。
这可能更可行,因为这样指令完全控制事件的绑定和处理。
所以,最终的实现步骤可能是:
-
在指令的mounted钩子中,解构binding.value,获取handler、event(默认input)、delay(默认300)。
-
给元素添加指定的事件监听器,当事件触发时,执行防抖处理,即在delay时间后执行handler。
-
在元素卸载前(beforeUnmount钩子),移除事件监听器,避免内存泄漏。
同时,需要注意防抖函数的作用域,确保每次事件触发时使用的是同一个timeout变量。可以将timeout变量保存在元素对象上,或者通过闭包保存。
比如:
const debounceDirective = {
mounted(el, binding) {
const defaultEvent = 'input';
const defaultDelay = 300;
// 如果binding.value是一个函数,说明用户只传了handler
let event = defaultEvent;
let delay = defaultDelay;
let handler = binding.value;
// 如果binding.value是对象,则解构
if (typeof binding.value === 'object') {
handler = binding.value.handler;
event = binding.value.event || defaultEvent;
delay = binding.value.delay || defaultDelay;
} else if (typeof binding.value === 'function') {
handler = binding.value;
} else {
console.error('v-debounce指令需要传递一个函数或配置对象');
return;
}
// 保存防抖的timeout ID到el对象上
el._debounceTimeout = null;
el._debounceHandler = function(...args) {
clearTimeout(el._debounceTimeout);
el._debounceTimeout = setTimeout(() => {
handler(...args);
}, delay);
};
el.addEventListener(event, el._debounceHandler);
},
beforeUnmount(el, binding) {
const event = ...; // 需要获取之前绑定的事件类型,可能需要存储
// 这里需要保存event,或者在元素上存储该信息
// 所以在mounted的时候,可能需要在el上存储event和handler
if (el._debounceEvent) {
el.removeEventListener(el._debounceEvent, el._debounceHandler);
el._debounceTimeout = null;
el._debounceHandler = null;
el._debounceEvent = null;
}
}
}
//但这样在beforeUnmount时需要知道之前绑定的事件类型,所以必须在mounted的时候将event存储在el对象上。
所以改进后的代码:
mounted(el, binding) {
// 解析参数
let event = 'input';
let delay = 300;
let handler;
if (typeof binding.value === 'function') {
handler = binding.value;
} else if (typeof binding.value === 'object') {
handler = binding.value.handler;
event = binding.value.event || event;
delay = binding.value.delay || delay;
} else {
console.error('v-debounce指令的值必须为函数或对象');
return;
}
// 保存到el上,以便unmount时使用
el._debounce = {
event,
handler: (...args) => {
clearTimeout(el._debounce.timeout);
el._debounce.timeout = setTimeout(() => {
handler(...args);
}, delay);
},
timeout: null
};
el.addEventListener(event, el._debounce.handler);
},
beforeUnmount(el) {
if (el._debounce) {
el.removeEventListener(el._debounce.event, el._debounce.handler);
clearTimeout(el._debounce.timeout);
el._debounce = null;
}
}
这样,在元素卸载时,可以正确移除事件监听器,并清除定时器。
另外,还需要处理参数中的事件类型和延迟时间。比如用户可能通过指令的参数来指定事件类型,而不是在value对象中。例如:
<input v-debounce:keyup="handler" />
这时候,binding.arg的值是'keyup',可以优先使用arg作为事件类型。
所以需要调整代码,优先使用binding.arg作为事件类型,如果存在的话。
同样,延迟时间也可以通过参数传递,比如:
<input v-debounce:keyup.500="handler" />
但这里的修饰符会被解析为{500: true},这时候可能需要从修饰符中提取数值。例如:
在mounted钩子中:
// 事件类型由arg决定
const event = binding.arg || 'input';
// 延迟时间从修饰符中提取,比如修饰符是500,则delay是500
let delay = 300;
const modifiers = Object.keys(binding.modifiers);
if (modifiers.length > 0) {
const possibleDelay = parseInt(modifiers[0]);
if (!isNaN(possibleDelay)) {
delay = possibleDelay;
}}
或者,用户可以通过value对象传递delay,或者直接传递数值作为delay:
当binding.value是数值时,delay为这个数值,handler需要另外处理?这可能复杂,因为handler必须存在。
所以可能更合理的处理是:
如果binding.arg存在,作为事件类型;
delay可以从修饰符中提取,或者从value对象中提取,或者value为delay数值,同时handler通过其他方式传递?这似乎不太可行。
可能更好的方式是,当用户想要自定义事件类型时,使用参数,delay通过value传递,或者通过修饰符?
这可能比较复杂,所以可能需要重新考虑设计,让用户通过参数和value来传递必要的信息。
例如:
指令的参数是事件类型;
value可以是一个函数(作为handler,delay默认300),或者是一个对象包含handler和delay。
或者,value可以是函数,而delay通过修饰符传递,例如:
点击
此时,binding.arg是'click',修饰符对象是{500: true},所以需要从修饰符中提取延迟时间。
实现的话:
在mounted钩子中:
const event = binding.arg || 'input';
let delay = 300;
// 检查修饰符,寻找可能的数值
const delayModifier = Object.keys(binding.modifiers).find(m => !isNaN(m));
if (delayModifier) {
delay = parseInt(delayModifier);
}
// 或者,如果用户通过value传递delay,则覆盖
if (typeof binding.value === 'object') {
delay = binding.value.delay || delay;
handler = binding.value.handler;
} else if (typeof binding.value === 'function') {
handler = binding.value;
}
这样,用户可以通过修饰符指定延迟时间,或者通过value对象中的delay属性。
但这种方法可能需要处理多个修饰符的情况,比如可能有多个数值,这时候需要决定取哪一个。
或者,如果用户使用类似v-debounce:input.500="handler",则修饰符是500,此时delay为500。
这样,在代码中:
modifiers = Object.keys(binding.modifiers);
if (modifiers.length > 0) {
const possibleDelay = parseInt(modifiers[0]);
if (!isNaN(possibleDelay)) {
delay = possibleDelay;
}
}
这样就能提取出数值型的修饰符作为延迟时间。
这样,用户就可以这样使用指令:
其中,事件类型是input,延迟500ms,处理函数是onInput。
此时,binding.value是onInput函数,binding.arg是input,修饰符是500: true。
这样,在指令中的处理逻辑是:
事件类型是binding.arg || 'input';
delay从修饰符中提取第一个数值,否则默认300;
handler是binding.value;
如果binding.value是一个对象,可能需要其他处理,但在这个例子中,用户传递的是函数,所以需要调整之前的代码,允许处理这种情况。
例如,在mounted钩子中:
const event = binding.arg || 'input';
let delay = 300;
const modifiers = Object.keys(binding.modifiers);
modifiers.forEach(mod => {
const num = parseInt(mod);
if (!isNaN(num)) {
delay = num;
}
});
let handler;
if (typeof binding.value === 'function') {
handler = binding.value;
} else {
console.error('v-debounce指令的值必须是一个函数');
return;
}
然后绑定事件。
这样,用户就可以用v-debounce:事件类型.延迟时间="处理函数"的方式来使用指令。
例如:
<button v-debounce:click.500="handleClick">点击</button>
这样,事件类型是click,延迟500ms,处理函数是handleClick。
这应该比较简洁,用户也容易理解。
那么,最终的指令代码大致如下:
export const debounceDirective = {
mounted(el, binding) {
const event = binding.arg || 'input';
let delay = 300;
const modifiers = Object.keys(binding.modifiers);
// 从修饰符中提取延迟时间
modifiers.forEach(mod => {
const parsed = parseInt(mod);
if (!isNaN(parsed)) {
delay = parsed;
}
});
// 如果binding.value不是函数,报错
if (typeof binding.value !== 'function') {
console.error('v-debounce指令的值必须是一个函数');
return;
}
const handler = binding.value;
// 保存到el上,以便卸载时使用
el._debounce = {
event,
handler: function(...args) {
clearTimeout(el._debounce.timeoutId);
el._debounce.timeoutId = setTimeout(() => {
handler.apply(this, args);
}, delay);
},
timeoutId: null
};
// 添加事件监听
el.addEventListener(event, el._debounce.handler);
},
beforeUnmount(el) {
if (el._debounce) {
el.removeEventListener(el._debounce.event, el._debounce.handler);
clearTimeout(el._debounce.timeoutId);
delete el._debounce;
}
}
};
这样,用户就可以在模板中这样使用:
<template>
<input v-debounce:input.300="handleInput" />
<button v-debounce:click.500="handleClick">点击</button>
</template>
这样的写法比较直观,事件类型通过参数传递,延迟时间通过修饰符(数值)传递,处理函数作为指令的值。
需要注意的是,修饰符在Vue中通常作为键存在,所以例如.500会被视为一个修饰符键名为"500",其值为true。所以上述代码通过遍历修饰符,解析其中的数值,从而得到延迟时间。如果有多个数值修饰符,这里会取最后一个,比如.300.500会取500,但这种情况用户应该避免,应该只传递一个数值修饰符。
此外,如果用户需要更复杂的配置,比如同时指定事件类型和延迟时间,但无法通过参数和修饰符实现,可能需要通过对象语法,但上述方法已经覆盖了大部分常见情况。
综上所述,这个自定义指令的实现应该满足用户的需求,允许通过参数指定事件类型,通过数值修饰符指定延迟时间,处理函数作为指令的值。在元素挂载时绑定事件,并在事件触发时使用防抖函数,同时在组件卸载前清理事件监听器和定时器,避免内存泄漏。
在 Vue 3 中实现自定义防抖指令可以通过以下步骤完成。该指令允许你指定事件类型和延迟时间,并在事件触发时执行防抖处理函数。
完整代码实现
const debounceDirective = {
mounted(el, binding) {
// 默认事件类型为 'input',延迟时间 300ms
const event = binding.arg || 'input';
let delay = 300;
// 从修饰符中提取延迟时间(如 .500 表示 500ms)
const modifiers = Object.keys(binding.modifiers);
modifiers.forEach(mod => {
const parsedDelay = parseInt(mod);
if (!isNaN(parsedDelay)) {
delay = parsedDelay;
}
});
// 确保绑定值是一个函数
if (typeof binding.value !== 'function') {
console.error('v-debounce 必须绑定一个函数');
return;
}
const handler = binding.value;
// 存储防抖函数及相关参数到元素上
el._debounce = {
event,
handler: (...args) => {
clearTimeout(el._debounce.timeoutId);
el._debounce.timeoutId = setTimeout(() => {
handler(...args);
}, delay);
},
timeoutId: null
};
// 添加事件监听
el.addEventListener(event, el._debounce.handler);
},
beforeUnmount(el) {
// 组件卸载前移除事件监听并清除定时器
if (el._debounce) {
el.removeEventListener(el._debounce.event, el._debounce.handler);
clearTimeout(el._debounce.timeoutId);
delete el._debounce;
}
}
};
// 全局注册指令
app.directive('debounce', debounceDirective);
使用示例
<template>
<!-- 输入框示例:监听 input 事件,防抖 300ms -->
<input v-debounce:input="handleInput" />
<!-- 按钮示例:监听 click 事件,防抖 500ms -->
<button v-debounce:click.500="handleClick">点击我</button>
</template>
<script setup>
const handleInput = (event) => {
console.log('防抖后的输入值:', event.target.value);
};
const handleClick = () => {
console.log('按钮点击,防抖处理');
};
</script>
我们还可以再次的进行封装directive文件
import Highlight from "../help/highlight";// 单独生产一个文件
import Color from "../help/color";
import Debounce from "../help/debounce";
const directives = { //汇总自定义指令
// 此处可进行多个指令
Highlight,//文本高亮指令,
Color,//文本颜色指令
Debounce,//防抖指令
}
export default { //导出自定义指令
install(app) {// 以安装的方式插到app中
Object.keys(directives).forEach((key) => { // 遍历directives对象的key
app.directive(key, directives[key]) // 将每个directive注册到app中
})
}
}
然后是main.js 文件
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import directives from './directives/index'
const app = createApp(App)
app.use(directives)//
app.use(store)
app.use(router)
app.mount('#app')
这个也是一个全局注册的方法
指令说明
- 事件类型:通过指令参数指定,如
:input
、:click
,默认是input
。 - 延迟时间:通过数值修饰符指定(如
.500
表示 500ms),默认 300ms。 - 处理函数:绑定到指令的函数,事件触发时执行防抖后的函数。
关键点解释
- 事件绑定:在
mounted
生命周期钩子中,根据参数和修饰符配置事件监听。 - 防抖逻辑:每次事件触发时清除之前的定时器,重新设置新的定时器。
- 内存管理:在
beforeUnmount
钩子中移除事件监听器并清除定时器,防止内存泄漏。 - 灵活性:支持动态调整事件类型和延迟时间,适应不同场景需求。
通过这种方式,你可以轻松在 Vue 3 项目中复用防抖逻辑,提升交互性能。
如觉得本文对你有帮助的话,欢迎点赞❤❤❤,写作不易,持续输出的背后是无数个日夜的积累,您的点赞是持续写作的动力,感谢支持!有什么写错的,需要增加的可以在评论区留言 谢谢大家支持