Vue自定义指令
指令
指令 (Directives): 是带有 v- 前缀的特殊属性, 职责是,当表达式的值改变时, 将其产生的连带影响,响应式地作用于 DOM。
内置指令
先来看看Vue中的内置指令
-
v-bind: 响应并更新DOM特性;例如:v-bind:href v-bind:class v-bind:title v-bind:bb
-
v-on:用于监听DOM事件; 例如:v-on:click v-on:keyup
-
v-model:数据双向绑定;用于表单输入等;例如:
<input v-model="message">
-
v-show:条件渲染指令,为DOM设置css的style属性
-
v-if:条件渲染指令,动态在DOM内添加或删除DOM元素
-
v-else:条件渲染指令,必须跟v-if成对使用
-
v-for:循环指令;例如:
<li v-for="(item,index) in todos"></li>
-
v-else-if:判断多层条件,必须跟v-if成对使用
-
v-text:更新元素的textContent;例如:
<span v-text="msg"></span>
等同于
<span>{{msg}}</span>
-
v-html:更新元素的innerHTML
-
v-pre:不需要表达式,跳过这个元素以及子元素的编译过程,以此来加快整个项目的编译速度;例如:
<span v-pre>{{ this will not be compiled }}</span>
-
v-cloak:不需要表达式,这个指令保持在元素上直到关联实例结束编译
-
v-once:不需要表达式,只渲染元素或组件一次,随后的渲染,组件/元素以及下面的子元素都当成静态页面不在渲染
自定义指令
局部自定义指令
<template>
<div>
<span v-multiply="number"></span>
<br>
<br>
<span>number:{{number}}</span>
<br>
<br>
<button @click="number++">操作</button>
</div>
</template>
<script>
export default {
name: 'WorkspaceJsonTestCom',
data() {
return {
number: 1
};
},
directives: {
}
};
</script>
函数式
先来看看函数式的参数
-
element
指令所绑定的元素,可以用来直接操作 DOM 。
-
binding
-
name:指令名,不包含v-的前缀;
-
value:指令的绑定值;例如:v-my-directive=“1+1”,value的值是2;
-
oldValue:指令绑定的前一个值,仅在update和componentUpdated钩子函数中可用,无论值是否改变都可用;
-
expression:绑定值的字符串形式;例如:v-my-directive=“1+1”,expression的值是'1+1';
-
arg:传给指令的参数;例如:v-my-directive:foo,arg的值为 ‘foo’;
-
modifiers:一个包含修饰符的对象;例如:v-my-directive.a.b,modifiers的值为{‘a’:true,‘b’:true}
-
-
vnode
Vue编译的生成虚拟节点。
-
oldVnode
上一次的虚拟节点,仅在update和componentUpdated钩子函数中可用。
现在以函数式实现一个简单的功能,使用自定义v-multiply将number*10并展示在页面
directives: {
multiply(element, binding, vnode, oldVnode) {
element.innerText = '指令number:' + binding.value * 10
}
}
效果
对象式
再来看看对象式
对象式有着自己的生命周期函数
- 页面加载时:bind inserted
- 更新组件:update componentUpdated
- 卸载组件:unbind
- 重新安装组件:bind inserted
注意区别:bind与inserted:bind时父节点为null,inserted时父节点存在;update与componentUpdated:update是数据更新前,componentUpdated是数据更新后。
还是上面的功能,以对象式完成
directives: {
// 对象式
multiply: {
// 指令与元素成功绑定
bind(element, binding) {
element.innerText = '指令number:' + binding.value * 10
},
// 指令所在元素被插入页面式
inserted(element, binding) {
},
// 指令所在的模板被重新解析时
update(element, binding) {
element.innerText = '指令number:' + binding.value * 10
}
}
}
效果
全局自定义指令
使用组件的directives选项注册局部自定义指令只能在该组件内使用,在别的组件使用会报错。
接下来使用Vue.directive(id,definition)注册全局自定义指令
感觉和过滤器一样😀
函数式
Vue.directive('multiply', function(element, binding) {
element.innerText = '指令number:' + binding.value * 10
})
对象式
Vue.directive('multiply', {
// 指令与元素成功绑定
bind(element, binding) {
element.innerText = '指令number:' + binding.value * 10
},
// 指令所在元素被插入页面式
inserted(element, binding) {
},
// 指令所在的模板被重新解析时
update(element, binding) {
element.innerText = '指令number:' + binding.value * 10
}
}
)
一些小坑
命名
在定义指令名字的时候如果很长一般以变量的习惯会以驼峰命名
<span v-multiplyXxxx="number"></span>
但是以Vue内置指令如v-else-if,官方是不建议这么写的然后改一改
这时候就不能简写了,要写成下面这样
this的问题
我们输出看看指令函数中的this
这是函数式中的
这是对象式中的
可以看到在这里面的this并不是Vm实例,所以不要搞混了哦😉