vue
中的自定义指令
简述
Vue
框架给我们提供了许多指令,例如v-if 、v-else、 v-html、v-show、v-text、v-model、v-bind等等,这些指令都是固定的,并不能任意满足我们。Vue
除了提供了默认内置的指令外,还允许开发人员根据实际情况自定义指令,称为“自定义指令”,它的作用价值在于当开发人员在某些场景下需要对普通DOM元素进行操作的时候。
注册自定义指令
Vue
自定义指令和组件一样存在着全局注册和局部注册两种方式
注册全局指令
通过 Vue.directive( id, [definition] )
方式注册全局指令,第一个参数为自定义指令名称(指令名称不需要加 v-
前缀,默认是自动加上前缀的,使用指令的时候一定要加上前缀),第二个参数可以是对象数据,也可以是一个指令函数。
声明语法
:
// 1. 声明全局指令
Vue.directive(指令名称,{ 配置对象成员 })
// 配置对象:
inserted(m){
m:代表使用该指令的html标签dom对象,可以通过m进行原始dom操作实现业务需求
}
注意
:
私有指令directives关键字 与el、data等都是并列的
简单案例
:
<div id="app" class="demo">
<input type="text" v-focus>
</div>
<script>
// 全局注册
Vue.directive("focus", {
inserted: function(el) {
el.focus();
}
})
new Vue({
el: "#app"
})
</script>
这个简单案例当中,我们通过注册一个 v-focus
指令,实现了在页面加载完成之后自动让输入框获取到焦点的小功能。
注册局部指令
通过在Vue
实例中添加 directives
对象数据注册局部自定义指令。
<div id="app" class="demo">
<!-- 局部注册 -->
<input type="text" v-focus2>
</div>
<script>
new Vue({
el: "#app",
directives: {
focus2: {
inserted: function(el) {
el.focus();
}
}
}
})
</script>
钩子函数
一个指令定义对象可以提供如下几个钩子函数 (均为可选):
bind
:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。inserted
:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。update
:所在组件的VNode
更新时调用。componentUpdated
:指令所在组件的VNode
及其子VNode
全部更新后调用。unbind
:只调用一次,指令与元素解绑时调用。
<div id="app">
<input type="text" v-test>
</div>
<script src="vue.js"></script>
<script>
// 注册全局自定义指令
Vue.directive('test', {
// 第一个钩子函数 bind 指令第一次绑定到元素上
bind: function(el, binding) {
console.log('bind') // bind
},
// 第二个钩子函数 inserted 指令所在的元素插入到父节点
inserted: function(el, binding) {
console.log('inserted') // inserted
},
// 第三个钩子函数 update 数据发生变化
update: function(el, binding) {
console.log('update')
},
// 第四个钩子函数 componentUpdated 更新完毕
componentUpdated: function(el, binding) {
console.log('componentUpdated')
},
// 第五个钩子函数 unbind 解绑
unbind: function(el, binding) {
console.log('unbind')
}
})
new Vue({
el: '#app'
})
</script>
参数
el
指令所绑定的元素,可以用来直接操作 DOM
binding
一个对象,包含以下属性:
name: 指令名,不包括 v- 前缀
value: 指令的绑定值,例如:v-my-directive=“1 + 1” 中,绑定值为 2
oldValue: 指令绑定的前一个值,仅在 update 和 componentUpdated 钩子中可用。无论值是否改变都可用
expression: 字符串形式的指令表达式。例如 v-my-directive=“1 + 1” 中,表达式为 “1 + 1”
arg: 传给指令的参数,可选。例如 v-my-directive:foo 中,参数为 “foo”
modifiers: 一个包含修饰符的对象。例如:v-my-directive.foo.bar 中,修饰符对象为 { foo: true, bar: true }
<div id="app">
<div class="txt" v-test:aaa.trim="100+2"></div>
</div>
<script src="vue.js"></script>
<script>
Vue.directive('test', {
inserted: function(el, binding) {
el.innerText = binding.value
console.log(el) // 绑定的元素: <div class="txt"></div>
console.log(binding.name) // 指令名字: test
console.log(binding.value) // 值: 102
console.log(binding.expression) // 表达式: 100+2
console.log(binding.arg) // 指令参数: aaa
console.log(binding.modifiers) // 指令修饰符: {trim: true}
}
})
new Vue({
el: '#app'
})
</script>
vnode
Vue 编译生成的虚拟节点
oldVnode
上一个虚拟节点,仅在 update 和 componentUpdated 钩子中可用
注意
除了 el 之外,其它参数都应该是只读的,切勿进行修改。如果需要在钩子之间共享数据,建议通过元素的 dataset 来进行
建议在给指令的命名时采用小驼峰式的命名方式,比如changeBackgroundColor,在使用的时候采用烤串式写法 v-change-background-color
简单案例
<div id="app">
<input type="text" v-inputStyle:bgcolor="bgColor" v-inputStyle:fsize="fSize">
</div>
<script src="vue.js"></script>
<script>
Vue.directive('inputStyle', {
inserted(el, binding) {
// 背景颜色
if (binding.arg === 'bgcolor') {
el.style.background = binding.value
}
// 字体大小
if ( binding.arg === 'fsize') {
el.style.fontSize = binding.value
}
}
})
new Vue({
el: '#app',
data: {
bgColor: 'blue',
fSize: '18px'
}
})
</script>