简介
除了核心功能默认内置的指令 (v-model 和 v-show),Vue 也允许注册自定义指令。注意,在 Vue2.0 中,代码复用和抽象的主要形式是组件。然而,有的情况下,你仍然需要对普通 DOM 元素进行底层操作,这时候就会用到自定义指令。
API地址:https://vue3js.cn/docs/zh/api/application-api.html#directive
钩子函数
一个指令定义对象可以提供如下几个钩子函数 (均为可选):
- beforeMount:当指令第一次绑定到元素并且在挂载父组件之前调用。在这里你可以做一次性的初始化设置。
- mounted:在挂载绑定元素的父组件时调用。
- beforeUpdate:在更新包含组件的 VNode 之前调用。
- updated:在包含组件的 VNode 及其子组件的 VNode 更新后调用。
- beforeUnmount:在卸载绑定元素的父组件之前调用
- unmounted:当指令与元素解除绑定且父组件已卸载时,只调用一次。
基本和vue组件的生命周期类似,只是没有create的阶段,直接进入挂载阶段,生命周期如下
- beforeCreate
- created
- beforeMount
- mounted
- beforeUpdate
- updated
- beforeUnmount(vue2.0是beforeDestroy)
- unmounted(vue2.0是destroyed)
使用方式
自定义指令可以全局注册也可以局部注册。全局注册就是挂载到createApp()的结果上,局部注册就是在组件内提供了directives属性,在这里面进行注册。
写一个input的自动聚焦的示例,代码如下:
局部注册
<template>
<div>
<input v-focus />
</div>
</template>
<script>
export default {
directives: {
focus: {
// 指令的定义
mounted(el) {
el.focus()
}
}
}
}
</script>
全局注冊
注意这里的挂载顺序,最后写app.mount(),不然会报错。
main.js
import { createApp } from 'vue'
import App from './App.vue'
const app = createApp(App);
// 定义v-focus指令
app.directive('focus', {
mounted(el) {
el.focus();
}
});
app.mount('#app');
example.vue
<template>
<div>
<input v-focus />
</div>
</template>
指令参数
指令的参数可以是动态的。例如,在 v-mydirective:[argument]="value" 中,argument 参数可以根据组件实例数据进行更新!这使得自定义指令可以在应用中被灵活使用。
如果指令参数有多个,也可以传一个对象。
就拿刚刚的v-focus示例来说,如果我们需要将其边框的宽度或颜色修改掉,该如何做呢?
示例
main.js
import { createApp } from 'vue'
import App from './App.vue'
const app = createApp(App);
// 定义v-focus指令
app.directive('focus', {
mounted(el, binding) {
el.focus();
if (typeof binding.value !== 'object') {
el.style.borderColor = binding.value;
} else {
el.style.borderColor = binding.value.color;
el.style.borderWidth = binding.value.borderWidth;
}
}
});
app.mount('#app');
App.vue
<template>
<div>
<input v-focus="yellowColor" />
<input v-focus:[color]="blueColor" />
<input v-focus="{ color: 'red', borderWidth: '18px' }" />
</div>
</template>
<script>
import { defineComponent } from '@vue/composition-api'
export default defineComponent({
data() {
return {
color: 'color',
yellowColor: 'yellow',
blueColor: 'blue'
};
}
})
</script>
<style scoped>
input { margin: 20px; display: block; }
</style>
由于这里focus只能对一个input起作用,所以反应在了最后一个input上面。
函数简写
在很多时候,你可能想在 mounted 和 updated 时触发相同行为,而不关心其它的钩子。比如这样写:
// 定义v-focus指令
app.directive('focus',(el, binding)=> {
el.focus();
if (typeof binding.value !== 'object') {
el.style.borderColor = binding.value;
} else {
el.style.borderColor = binding.value.color;
el.style.borderWidth = binding.value.borderWidth;
}
});
也就是app.directive提供了两种入参方式,一种是第二参数写成对象,里面包含各个生命周期的钩子函数,另外一个简写就是第二个参数直接写成函数,只在mounted和updated这两个常用的钩子函数触发条件下执行。
网友评论