Vue3
Vue.js的版本更新到了Vue 3之后,对于自定义指令也有所改变。在Vue 2中,我们可以通过bind、inserted、update等钩子函数来控制自定义指令的行为。但是在Vue 3中,这些钩子函数被重命名并放置在不同的位置上。
下面是Vue 3中常用的自定义指令钩子函数及其作用:
beforeMount: 在元素首次挂载前调用,类似于Vue 2中的bind钩子函数。
app.directive('my-directive', {
beforeMount(el) {
// 在元素首次挂载前执行的操作
}
})
mounted: 在元素挂载完成后调用,类似于Vue 2中的inserted钩子函数。
app.directive('my-directive', {
mounted(el) {
// 在元素挂载完成后执行的操作
}
})
updated: 当组件或者DOM发生更新时调用,类似于Vue 2中的update钩子函数。
app.directive('my-directive', {
updated(el) {
// DOM更新后执行的操作
}
})
unmounted: 在元素从页面移除时调用,相当于Vue 2中的unbind钩子函数。
app.directive('my-directive', {
unmounted(el) {
// 元素从页面移除时执行的操作
}
})
需要注意的是,由于Vue 3使用了Composition API,因此在编写自定义指令时应该将逻辑包装在一个单独的函数内部,然后再导入到主文件中进行全局注册。
Vue2
Vue.js的自定义指令可以通过使用directive选项来创建。在自定义指令中,我们可以定义不同的钩子函数来控制指令的行为。
下面是常见的自定义指令钩子函数及其作用:
bind: 当指令第一次被绑定到元素时调用。这里可以进行初始化操作或者添加事件监听器等。
// Vue组件内部示例
export default {
directives: {
myDirective: {
bind(el, binding) {
// 初始化操作或者添加事件监听器等
}
}
}
}
inserted: 当指令所在的元素被插入到DOM中后调用。此时,该元素已经存在于页面上了。
// Vue组件内部示例
export default {
directives: {
myDirective: {
inserted(el, binding) {
// DOM元素已经插入到页面上
}
}
}
}
update: 当指令所在的元素更新时调用。比如,当绑定的值发生变化时会触发该钩子函数。
// Vue组件内部示例
export default {
directives: {
myDirective: {
update(el, binding) {
// 处理指令相关的更新逻辑
}
}
}
}
componentUpdated: 当指令所在的组件更新完成之后调用。与updated类似,只是它是在组件本身及其子组件都更新完成后才调用。
// Vue组件内部示例
export default {
directives: {
myDirective: {
componentUpdated(el, binding) {
// 处理指令相关的更新逻辑(包括子组件)
}
}
}
}
unbind: 当指令从元素上移除时调用。可以清理工作、删除事件监听器等。
// Vue组件内部示例
export default {
directives: {
myDirective: {
unbind(el, binding) {
// 清理工作、删除事件监听器等
}
}
}
}
编写防抖和节流指令
防抖
// src/directive/debounce.js
const debounce = {
mounted(el, binding) {
console.log('指令挂载了');
el.timer = null
el.handler = function () {
if (el.timer) {
clearTimeout(el.timer)
}
el.timer = setTimeout(() => {
binding.value.fn()
el.timer = null
}, binding.value.delay)
}
el.addEventListener(binding.value.event, el.handler)
},
unmounted(el, binding) {
console.log('在元素从页面移除时调用');
if (el.timer) {
clearTimeout(el.timer);
el.timer = null;
}
el.removeEventListener(binding.value.event, el.handler)
}
}
export default debounce
节流
// src/directive/trottle.js
const trottle = {
mounted(el, binding) {
console.log('节流指令挂载了');
el.timer = null
el.handler = function () {
if (el.timer) {
return;
}
el.timer = setTimeout(() => {
binding.value.fn()
el.timer = null
}, binding.value.delay)
}
el.addEventListener(binding.value.event, el.handler)
},
unmounted(el, binding) {
console.log('在元素从页面移除时调用trottle');
if (el.timer) {
clearTimeout(el.timer);
el.timer = null;
}
el.removeEventListener(binding.value.event, el.handler)
}
}
export default trottle
注册
import { createApp } from 'vue'
import App from './App.vue'
import debounce from './directive/debounce';
import throttle from './directive/throttle';
const app = createApp(App)
app.directive("debounce", debounce);
app.directive('throttle',throttle)
app.mount("#app");
使用
<script setup>
const handleClick = () => {
console.log('防抖点击');
}
</script>
<template>
<button v-debounce="{ fn: handleClick, event: 'click', delay: 1000 }">点击试试</button>
<input v-debounce="{ fn: handleClick, event: 'input', delay: 1000 }"/>
<hr>
<button v-throttle="{ fn: handleClick, event: 'click', delay: 1000 }">点击试试</button>
<input v-throttle="{ fn: handleClick, event: 'input', delay: 1000 }"/>
</template>