Vue的自定义指令
-
- 简介
- 钩子函数
- 钩子函数参数
-
- 动态指令参数
- 函数简写
- 对象字面量
- 项目中使用
- Vue源码学习目录
你越是认真生活,你的生活就会越美好
——弗兰克·劳埃德·莱特
《人生果实》经典语录
自定义指令-vue官网
简介
Vue
除了核心功能默认内置的指令 (
v-model
和
v-show
),Vue 也允许
注册自定义指令
。
注意,在
Vue2.0
中,
代码复用
和
抽象
的主要形式是
组件
。然而,有的情况下,你仍然需要
对普通 DOM 元素进行底层操作
,这时候就会用到
自定义指令
。
举个聚焦输入框的例子,如下:
当页面加载时,
该元素将获得焦点
(注意:
autofocus
在移动版 Safari 上不工作)。
事实上,只要你在打开这个页面后还没点击过任何内容,这个输入框就应当还是处于聚焦状态。现在让我们
用指令来实现这个功能
:
// 注册一个全局自定义指令 `v-focus`
Vue.directive('focus', {
// 当被绑定的元素插入到 DOM 中时……
inserted: function (el) {
// 聚焦元素
el.focus()
}
})
如果想注册
局部指令
,组件中也接受一个
directives
的选项:
directives: {
focus: {
// 指令的定义
inserted: function (el) {
el.focus()
}
}
}
然后你可以
在模板中
任何元素上使用新的
v-focus
property,如下:
钩子函数
一个指令定义对象可以提供如下几个
钩子函数
(均为可选):
-
:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。bind
-
:inserted
调用 (仅保证父节点存在,但不一定已被插入文档中)。被绑定元素插入父节点时
-
:所在组件的update
调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新 (详细的钩子函数参数见下)。VNode 更新时
-
:指令所在组件的 VNode 及其子 VNode 全部更新后调用。componentUpdated
-
:只调用一次,指令与元素解绑时调用。unbind
接下来我们来看一下钩子函数的参数 (即
el、binding、vnode 和 oldVnode
)。
钩子函数参数
指令钩子函数
会被传入以下参数:
-
:指令所绑定的元素,可以用来直接操作 DOM。el
-
:一个对象,包含以下 property:binding
-
:指令名,不包括 v- 前缀。name
-
:指令的绑定值,例如:value
中,绑定值为 2。v-my-directive="1 + 1"
-
:指令绑定的前一个值,仅在 update 和 componentUpdated 钩子中可用。无论值是否改变都可用。oldValue
-
:字符串形式的指令表达式。例如expression
中,表达式为v-my-directive="1 + 1"
。"1 + 1"
-
:传给指令的参数,可选。例如arg
中,参数为 “foo”。v-my-directive:foo
-
:一个包含修饰符的对象。例如:modifiers
中,修饰符对象为v-my-directive.foo.bar
。{ foo: true, bar: true }
-
-
:Vue 编译生成的虚拟节点。移步 VNode API 来了解更多详情。vnode
-
:上一个虚拟节点,仅在 update 和 componentUpdated 钩子中可用。oldVnode
除了
el
之外,
其它参数都应该是只读的
,
切勿进行修改
。如果需要在钩子之间
共享数据
,建议通过
元素的 dataset
来进行。
这是一个使用了这些 property 的自定义钩子样例:
Vue.directive('demo', {
bind: function (el, binding, vnode) {
var s = JSON.stringify
el.innerHTML =
'name: ' + s(binding.name) + '<br>' +
'value: ' + s(binding.value) + '<br>' +
'expression: ' + s(binding.expression) + '<br>' +
'argument: ' + s(binding.arg) + '<br>' +
'modifiers: ' + s(binding.modifiers) + '<br>' +
'vnode keys: ' + Object.keys(vnode).join(', ')
}
})
new Vue({
el: '#hook-arguments-example',
data: {
message: 'hello!'
}
})
动态指令参数
指令的参数可以是动态的。例如,在
v-mydirective:[argument]="value"
中,
argument
参数可以根据组件实例数据进行更新!这使得自定义指令可以在应用中被灵活使用。
例如你想要创建一个自定义指令,用来
通过固定布局将元素固定在页面上
。
我们可以像这样创建一个通过指令值来
更新竖直位置像素值
的自定义指令:
<div id="baseexample">
<p>Scroll down the page</p>
<p v-pin="200">Stick me 200px from the top of the page</p>
</div>
Vue.directive('pin', {
bind: function (el, binding, vnode) {
el.style.position = 'fixed'
el.style.top = binding.value + 'px'
}
})
new Vue({
el: '#baseexample'
})
这会
把该元素固定在距离页面顶部 200 像素
的位置。
但如果场景是我们需要把元素固定在左侧而不是顶部又该怎么办呢?这时使用
动态参数
就可以非常方便地根据每个组件实例来进行更新。
<div id="dynamicexample">
<h3>Scroll down inside this section ↓</h3>
<p v-pin:[direction]="200">I am pinned onto the page at 200px to the left.</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: '#dynamicexample',
data: function () {
return {
direction: 'left'
}
}
})
结果如下
这样这个自定义指令现在的灵活性就足以支持一些不同的用例了。
函数简写
在很多时候,你可能想在
bind
和
update
时触发相同行为,而不关心其它的钩子。比如这样写:
Vue.directive('color-swatch', function (el, binding) {
el.style.backgroundColor = binding.value
})
对象字面量
如果指令需要多个值,可以传入一个
JavaScript 对象字面量
。记住,指令函数能够接受所有合法的 JavaScript 表达式。
Vue.directive('demo', function (el, binding) {
console.log(binding.value.color) // => "white"
console.log(binding.value.text) // => "hello!"
})
项目中使用
src/plugins/directives.js
用于权限管理,在这里主要是判断是否有对应的编辑权限,来决定相关按钮是否展示
import Vue from 'vue'
import { getAlias } from '@/utils/tool'
import store from '../store'
const directives = {
// 权限配置
permission: {
inserted(el, { arg }) {
// getAlias()方法返回登录角色的权限别名数组 arg是使用自定义组件时传入的别名 如果传入的权限别名不在数组里 就会去掉对应的元素 不展示
if (getAlias(store.state.permissionTree).includes(arg)) return
let parent = el.parentElement
parent.removeChild(el)
}
}
}
// 全局directives
Object.keys(directives).forEach((directiveName) => {
Vue.directive(directiveName, directives[directiveName])
})
src/main.js 引入
组件里使用如下(
update-account
是编辑账号的权限别名)
v-permission
自定义指令功能 如果有这个权限就正常展示div的元素,如果没有这个权限就隐藏起来
<div class="footer" v-permission:update-account>
<!--相关按钮-->
</div>
Vue源码学习目录
Vue源码学习完整目录
谢谢你阅读到了最后~
期待你关注、收藏、评论、点赞~
让我们一起 变得更强