自定义指令
除了核心功能默认内置的指令 (例如 v-model 和 v-show),Vue 也允许注册自定义指令
有的情况下,你仍然需要对普通 DOM 元素进行底层操作,这时候就会用到自定义指令。
比如:获取文本框的焦点
自定义指令
- 定义一个全局的指令
const app = Vue.createApp({})
// 注册一个全局自定义指令 `v-focus`
// 参数1: 指令名
// 参数2: 指令的配置项
app.directive('focus', {
// 当被绑定的元素挂载到 DOM 中时……
mounted(el) {
// 聚焦元素
el.focus()
}
})
- 定义一个局部的指令
如果想注册局部指令,组件中也接受一个 directives 的选项:
directives: {
focus: {
// 指令的定义
mounted(el)
{
el.focus()
}
}
}
- 使用自定义指令
<input v-focus>
实现一个v-focus指令
<body>
<div id="app">
<input/>
<!--使用自定义指令-->
<input v-focus/>
<input/>
</div>
<script src="./node_modules/vue/dist/vue.global.js"></script>
<script>
const app = Vue.createApp({})
// 注册一个全局自定义指令 `v-focus`
// 参数1: 指令名
// 参数2: 指令的配置项
app.directive('focus', {
// 当被绑定的元素挂载到 DOM 中时……
mounted(el) {
// 聚焦元素
el.focus()
}
})
const vm = app.mount('#app')
window.vm = vm
</script>
</body>
指令的钩子函数
一个指令定义对象可以提供如下几个钩子函数 (均为可选):
created
:在绑定元素的 attribute 或事件监听器被应用之前调用。在指令需要附加在普通的 v-on 事件监听器调用前的事件监听器中时,这很有用。beforeMount
:当指令第一次绑定到元素并且在挂载父组件之前调用。mounted
:(重点) 当被绑定的元素挂载到 DOM 中后调用。beforeUpdate
:在更新包含组件的 VNode 之前调用。updated
:(重点) 在包含组件的 VNode 及其子组件的 VNode 更新后调用。beforeUnmount
:在卸载绑定元素的父组件之前调用unmounted
:当指令与元素解除绑定且父组件已卸载时,只调用一次。
钩子函数的参数
vue中一个完整的指令,格式为:v-指令名:指令的参数.指令的修饰符.指令的修饰符 = '指令的值'
,例如: v-on:click.stop.prevent = "clickFn"
所有的钩子函数的参数都是一个样,主要有两个参数el
和binding
- 参数1: el el表示指令所在的DOM元素
- 参数2: binding : 是一个对象,有很多属性,包含了指令中所有的信息
- arg: 传给指令的参数,可选 :参数。 例如
v-on:click.stop.prevent = "clickFn"
中,arg参数为 click - value: 指令的绑定值,例如
v-on:click.stop.prevent = "clickFn"
中,value值为 clickFn - modifiers: 指令的修饰符,可以有多个。例如
v-on:click.stop.prevent = "clickFn"
中,modifiers为 {stop: true, prevent: true}
- arg: 传给指令的参数,可选 :参数。 例如
实现一个v-on指令
<body>
<div id="app">
<a href="http://www.baidu.com" v-on:click.stop.prevent="clickFn">点我v-on</a> |
<!--使用自定义指令-->
<a href="http://www.baidu.com" v-myon:click.stop.prevent="clickFn">点我-v-myon</a>
</div>
<script src="./node_modules/vue/dist/vue.global.js"></script>
<script>
const app = Vue.createApp({
methods: {
clickFn() {
console.log("触发了点击事件...")
}
}
})
app.directive('myon', {
mounted(el, binding) {
console.log("el:", el)
console.log("binding:", binding)
console.log("arg:", binding.arg)
console.log("value:", binding.value)
console.log("modifiers:", binding.modifiers)
// 给el注册事件, 注册什么事件 binding.arg
el.addEventListener(binding.arg, function (e) {
// 保证传进来的clickFn在每次触发的时候都应该执行
binding.value()
if (binding.modifiers.prevent) {
e.preventDefault()
}
if (binding.modifiers.stop) {
e.stopPropagation()
}
})
}
})
const vm = app.mount('#app')
window.vm = vm
</script>
</body>
实现一个v-text指令
<span v-mytext="msg"></span>
自定义指令:
app.directive('mytext', {
mounted(el, binding) {
el.innerText = binding.value
}
})
实现一个v-color指令
<div v-color:bg="bgColor"> {{ bgColor }}</div>
<div v-color:font="fontSize">{{ fontSize }}</div>
自定义指令:
const app = Vue.createApp({
data() {
return {
fontSize: '40px',
bgColor: 'red'
}
}
})
app.directive('color', {
mounted(el, binding) {
if (binding.arg === 'font') {
el.style.fontSize = binding.value
}
if (binding.arg === 'bg') {
el.style.backgroundColor = binding.value
}
}
})
实现一个v-bind指令
<h1 v-mybind:title="msg">哈哈哈</h1>
自定义指令
app.directive('mybind', {
mounted(el, binding) {
el.setAttribute(binding.arg, binding.value)
}
})
指令的简写
在很多时候,你可能想在 mounted
和 updated
时触发相同行为,而不关心其它的钩子。比如这样写:
app.directive('color', (el, binding) => {
if (binding.arg === 'font') {
el.style.fontSize = binding.value
}
if (binding.arg === 'bg') {
el.style.backgroundColor = binding.value
}
})
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。