理论内容
介绍
除了默认设置的核心指令,Vue 也允许注册自定义指令。自定义指令好就好在可以很方便的将大量重复的事情通过一个简短的指令来实现。
- 使用场景:对 DOM 元素进行底层操作,比如:文本框获得焦点,修改元素字体颜色和大小
当页面加载时,想要输入框直接获得焦点,下面指令指令可以实现这个功能:
注册一个全局指令
// 注册一个全局自定义指令 `v-focus`
Vue.directive('focus', {
// 当被绑定的元素插入到 DOM 中时……
inserted: function (el) {
// 聚焦元素
el.focus()
}
})
注册一个局部指令
// 注册一个局部指令 `v-focus`
directives: {
focus: {
// 指令的定义
inserted: function (el) {
el.focus()
}
}
}
然后你可以在模板中任何元素上使用新的 v-focus 属性,如下:
<input v-focus>
只要你在打开这个页面后还没点击过任何内容,这个输入框就应当还是处于聚焦状态。
钩子函数
一个指令定义对象可以提供如下几个钩子函数 (均为可选):
- bind:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。
- inserted:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。
- update:所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新 (详细的钩子函数参数见下)。
- componentUpdated:指令所在组件的 VNode 及其子 VNode 全部更新后调用。
- unbind:只调用一次,指令与元素解绑时调用。
注:VNode是JavaScript对象。VNode表示Virtual DOM,用JavaScript对象来描述真实的DOM把DOM标签,属性,内容都变成对象的属性。
钩子函数参数
- el:指令所绑定的元素,可以用来直接操作 DOM。
- binding:一个对象。
- vnode:Vue 编译生成的虚拟节点。
- oldVnode:上一个虚拟节点,仅在 update 和 componentUpdated 钩子中可用。
除了 el 之外,其它参数都应该是只读的,切勿进行修改。
动态指令参数
指令的参数可以是动态的。
例如你想要创建一个自定义指令,用来通过固定布局将元素固定在页面上。我们可以像这样创建一个通过指令值来更新竖直位置像素值的自定义指令:
<div id="example">
<p v-pin="200">content</p>
</div>
Vue.directive('pin', {
bind: function (el, binding, vnode) {
el.style.position = 'fixed'
el.style.top = binding.value + 'px'
}
})
new Vue({
el: '#example'
})
这会把该元素固定在距离页面顶部 200 像素的位置。但如果场景是我们需要把元素固定在左侧而不是顶部又该怎么办呢?这时使用动态参数就可以非常方便地根据每个组件实例来进行更新。
<div id="example">
<p v-pin:[direction]="200">content</p>
</div>
Vue.directive('pin', {
bind: function (el, binding, vnode) {
el.style.position = 'fixed'
var s = (binding.arg == 'left' ? 'left' : 'top')
el.style[s] = binding.value + 'px'
}
})
new Vue({
el: '#example',
data: function () {
return {
direction: 'left'
}
}
})
这样这个自定义指令就有很多的灵活性了。
对象字面量
如果指令需要多个值,可以传入一个 JavaScript 对象字面量。记住,指令函数能够接受所有合法的 JavaScript 表达式。
<div v-demo="{ color: 'white', text: 'hello!' }"></div>
Vue.directive('demo', {
bind: function (el, binding, vnode) {
console.log(binding.value.color) // => "white"
console.log(binding.value.text) // => "hello!"
}
})
实际运用
组织全局自定义指令
- 首先单独创建一个directive.js文件,然后编写全局的自定义组件,例如定义一个直接修改Dom文字颜色的自定义组件
export default (Vue) => {
Vue.directive('editColor', {
inserted: function (el, binding) {
el.style.color = binding.value;
}
});
}
- 在main.js文件中引入directive.js文件,然后使用Vue.use(directive)调用
import Vue from 'vue';
import App from './App.vue';
import directive from './directive';
Vue.config.productionTip = false;
Vue.use(directive);
new Vue({
el: '#app',
components: {App},
})
- 在需要使用的地方调用你定义的组件名(需要加v-)。
<template>
<div class="hello-vue">
<p v-editColor="'gary'"> 自定义修改颜色值</p>
</div>
</template>
自定义局部指令
使用场景:某一个组件中经常重用的某些操作Dom的方法
- 写一个局部指令,例如定义一个直接修改Dom文字颜色的自定义组件
<script>
export default {
name: 'HelloWorld',
directives: {
// 自定义组件的名字
editFont: {
inserted: function (el, binding) {
el.style.fontSize = binding.value + "px";
}
}
}
}
</script>
- 在需要使用的地方调用。
<template>
<div class="hello-vue">
<p v-editFont="'50'"> 自定义修改字体大小</p>
</div>
</template>
上一篇:一篇搞懂vue常用指令