Vue 自定义指令的定义和调用
指令是 Vue 中以 v-
开头的一种属性,像 v-show
、v-model
都属于 Vue 的内置指令。除了内置的指令外,Vue 也允许自定义指令。自定义指令的功能就是操作 DOM。虽然 Vue 可以通过改变数据来操作 DOM,但有的功能还是无法实现,只能直接操作底层 DOM。
全局指令
全局指令可以在单独的 JS 文件中定义,定义完成后只需要在 main.js
中引入,所有组件都能使用。
下面定义一个改变元素字体颜色的指令:
export default Vue => {
// 定义指令
Vue.directive('color', {
// 元素被插入到父元素时调用
inserted(el) {
el.style.color = 'red' // 设置字体为红色
}
})
}
在 main.js
中引入和注册指令:
import color from './directive' // 引入指令
Vue.use(color) // 注册指令
在组件中调用指令:
<button v-color>按钮</button>
button
的字体颜色会变为红色。
指令可以通过 Vue.directive
来定义。
Vue.directive
的第一个参数是指令名称,第二个参数是配置对象,对象中包含了一些钩子函数。
下面是钩子函数说明:
bind
:只会调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。
inserted
:被绑定元素插入父节点时调用,此时已经可以获取父元素了。
update
:所在组件的虚拟 DOM 更新时调用。
componentUpdated
:指令所在组件的虚拟 DOM 及其子虚拟 DOM 全部更新后调用。
unbind
:只调用一次,指令与元素解绑时调用。
上面的几个钩子函数中 bind
和 inserted
可能会用的多一些。
钩子函数又可以接收几个参数,下面是参数说明:
el
:指令所绑定的元素,可以用来直接操作 DOM 。
binding
:一个对象,包含下面几个属性:
name
:指令名,不包含v-
前缀。value
:指令的绑定值,如果指令是v-color="1 + 1"
,value
的值就是2
。oldValue
:指令绑定的前一个值,仅在update
和componentUpdated
钩子中可用。无论值是否改变都可用。expression
:字符串形式的指令表达式。如果v-color="1 + 1"
,expression
的值就是1 + 1
。arg
:传给指令的参数,可选。如果v-color:bg
,arg
的值就是bg
。modifiers
:一个包含修饰符的对象。如果v-center.top.left
,modifiers
的值就是{top: true, left: true}
。
vnode
:Vue 编译生成的虚拟节点。
oldVnode
:上一个虚拟节点,仅在 update
和 componentUpdated
钩子中可用。
局部指令
局部指令需要在组件中的 directives
内定义。局部指令只能在定义的组件中使用。
下面用自定义局部指令实现页面打开后让 input
获取焦点:
<template>
<div id="app">
<input type="text" v-focus>
</div>
</template>
export default {
name: "app",
directives: {
// 定义名为 focus 的组件
focus: {
// 元素插入到父节点
inserted(el) {
el.focus() // 获取焦点
}
}
}
}
页面打开后 input
就能直接获取焦点。
局部指令的钩子函数和参数和全局指令是一样的。
对象字变量
如果指令需要多个值,可以传入一个 JavaScript 对象字面量。指令函数能够接受所有合法的 JavaScript 表达式。
指令:
Vue.directive('margin', {
inserted(el, binding) {
el.style.marginTop = binding.value.top + 'px'
el.style.marginLeft = binding.value.left + 'px'
}
})
调用:
<input type="text" v-margin="{top: 100, left: 100}">
最终 input
的 margin-top
和 margin-left
都 =
100px
。
相关文章:
版权声明:本文为原创文章,版权归 Mr. Ma's Blog 所有,转载请联系博主获得授权。
本文地址:https://www.misterma.com/archives/834/
如果对本文有什么问题或疑问都可以在评论区留言,我看到后会尽量解答。