1. 自定义指令
在 Vue.js 中,除了默认提供的核心指令(如 v-model
、v-show
、v-if
等),Vue.js 也允许注册自定义指令,自定义指令给你提供了一种方法来扩展 Vue 的功能,允许你直接在 DOM 元素上应用更底层的操作。
Vue除支持内置的v-model
/v-show
等指令,还允许自定义指令, vue2中,代码的复用和抽象的主要形式是组件,但在有些情况下仍然需要对普通dom元素做底层操作,这种情况下需要自定义指令,根据自定义指令的作用范围,可分为:全局、局部两种
自定义指令藏匿于 Vue 实例/组件实例的 directives
选项下,一个指令定义对象可以提供如下几个钩子函数(均为可选):
名称 | 作用 |
---|---|
bind | 只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置 |
inserted | 被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中) |
update | 所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新 (详细的钩子函数参数见下) |
componentUpdated | 指令所在组件的 VNode 及其子 VNode 全部更新后调用 |
unbind | 只调用一次,指令与元素解绑时调用 |
指令钩子函数会被传入以下参数:
el
:指令所绑定的元素,可以用来直接操作 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.foo.bar
,修饰符对象的值将为{ foo: true, bar: true }
。
vnode
:Vue 编译生成的虚拟节点。oldVnode
:上一个虚拟节点,仅在update
和componentUpdated
钩子中可用。
下面是一个自定义指令的基本例子,我们创建一个指令 v-focus
,该指令的作用是页面加载完毕后,元素将自动聚焦:
// 注册一个全局自定义指令 `v-focus`
Vue.directive('focus', {
// 当绑定元素插入到 DOM 中。
inserted: function (el) {
// 聚焦元素
el.focus();
}
});
// 在组件中局部注册
new Vue({
el: '#app',
directives: {
focus: {
// 指令的定义
inserted: function (el) {
el.focus();
}
}
}
})
使用方式如下:
<input v-focus>
自定义指令可以非常灵活地操作 DOM,赋予你高度的自由度来实现复杂的操作和行为,在实际应用时,它们通常用于操作元素的聚焦(focus)、触摸(touch)、动画(animation)等行为。
1.1 局部
通过自定义标签设置文字颜色
<div id="app">
<!--red绑定到data里面的变量-->
<p v-color="red">我是自定义指令</p>
</div>
var vm = new Vue({
el: '#app',
data: {
red:'red'
},
//自定义指令,局部
directives:{
color: {
inserted: function(el,binding) {
console.log(el,binding);
el.style.color = binding.value;
}
}
}
});
1.2 全局
<div id="app">
<!--red绑定到data里面的变量-->
<p v-color="red">我是自定义指令</p>
</div>
//自定义标签,全局
Vue.directive('color', {
inserted: function(el,binding) {
console.log(el,binding);
el.style.color = binding.value;
}
})
var vm = new Vue({
el: '#app',
data: {
red:'red'
}
});