需求

可以看到上面的输入框在刷新页面并没有进行自动聚焦,那么这时候可以使用自定义一个focus()
方法来处理。还有能否在刷新页面的时候,可以设置value
在文本框中以及设置字体颜色呢?能否进而通过传参的方式设置字体颜色呢?
这些都可以基于Vue的自定义指令来实现。
简介[1]
除了核心功能默认内置的指令 (v-model
和 v-show
),Vue 也允许注册自定义指令。注意,在 Vue2.0 中,代码复用和抽象的主要形式是组件。然而,有的情况下,你仍然需要对普通 DOM 元素进行底层操作,这时候就会用到自定义指令。
对于上面的需求,则需要自定义一个聚焦的focust
方法。
当页面加载时,该元素将获得焦点 (注意:autofocus 在移动版 Safari 上不工作)。事实上,只要你在打开这个页面后还没点击过任何内容,这个输入框就应当还是处于聚焦状态。现在让我们用指令来实现这个功能:
// 注册一个全局自定义指令 `v-focus`
Vue.directive('focus', {
// 当被绑定的元素插入到 DOM 中时……
inserted: function (el) {
// 聚焦元素
el.focus()
}
})
如果想注册局部指令,组件中也接受一个 directives
的选项:
directives: {
focus: {
// 指令的定义
inserted: function (el) {
el.focus()
}
}
}
然后你可以在模板中任何元素上使用新的 v-focus 属性,如下:
<input v-focus>
在上面定义自定义指令中,使用了inserted
这个钩子函数,另外还有更多的钩子函数。
钩子函数[2]
一个指令定义对象可以提供如下几个钩子函数 (均为可选):
-
bind
:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。 -
inserted
:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。 -
update
:所在组件的 VNode 更新时调用,「但是可能发生在其子 VNode 更新之前」。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新。 -
componentUpdated
:指令所在组件的 VNode 「及其子 VNode」 全部更新后调用。 -
unbind
:只调用一次,指令与元素解绑时调用。
bind:在列表中初始化输入框的值以及字体样式
「bind:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。」一般bind
只会去处理元素的样式、值等属性,不会去处理js
函数,因为有很多js
函数需要插入dom
内存中才可以处理,而bind
在之前,导致js
函数执行失败。可以考虑bind
是执行在window.onload
之前的行为。
directives: {
focus: {
bind: function (el) { // 每当指令绑定到元素上的时候,会立即执行这个 bind 函数,只执行一次
// 注意:在每个 函数中,第一个参数,永远是 el ,表示 被绑定了指令的那个元素,这个 el 参数,是一个原生的JS对象
// 在元素 刚绑定了指令的时候,还没有 插入到 DOM中去,这时候,调用 focus 方法没有作用
// 因为,一个元素,只有插入DOM之后,才能获取焦点
// el.focus()
// 在绑定元素的时候,可以设置初始化的值
el.value = 'bind func';
el.style.color = 'blue';
el.style.fontWeight = '700';
},
在这里focus()
方法是一个js
行为,需要元素插入dom
内存中才有效,所以,在这里,我只设置了元素内容以及样式。
inserted:在列表中实现该聚焦focus需求
「inserted 表示元素 插入到DOM中的时候,会执行 inserted 函数【触发1次】」一般inserted
方式是在bind
方法之后,类似windows.onload
加载完毕之后,所以相关执行的js
方法都是放到inserted
来进行处理。
首先在VM
中注册一个局部指令,如下:

在输入框上,设置自定义v-focus
指令,如下:

刷新页面,显示如下:

可以从页面看到,输入框既执行了bind
方法,也执行了inserted
方法。
其中,上面我在写bind
钩子函数的时候,写死了字体颜色,那么能否通过参数化,将参数传递进去呢?
接下来我们来看一下钩子函数的参数 (即 el
、binding
、vnode
和 oldVnode
)。
钩子函数参数[3]
指令钩子函数会被传入以下参数:
-
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 }
。 -
vnode
:Vue 编译生成的虚拟节点。移步 VNode API 来了解更多详情。 -
oldVnode
:上一个虚拟节点,仅在update
和componentUpdated
钩子中可用。
除了 el
之外,其它参数都应该是只读的,切勿进行修改。如果需要在钩子之间共享数据,建议通过元素的 dataset
来进行。
看了上面官网介绍的这些「钩子函数参数」我是比较迷糊的,不过,没关系。下面写个示例打印一下信息,就知道大概是怎么回事了。
打印钩子函数的参数信息
这个打印信息,我主要打印这几个常用的参数,用来刚才上面如何设置输入框的字体颜色。
-
binding
:一个对象,包含以下属性: -
name
:指令名,不包括v-
前缀。 -
value
:指令的绑定值,例如:v-my-directive="1 + 1"
中,绑定值为2
。 -
expression
:字符串形式的指令表达式。例如v-my-directive="1 + 1"
中,表达式为"1 + 1"
。
首先,我给自定义命令设置一个绑定的值,如下:

<input v-focus="'green'"
注意:我设置里面的是一个字符串'green'
,因为后续我要用来设置样式。
首先打印一下这三个参数会显示什么内容来看看。

浏览器打印信息如下:

那么下面只要基于提供的绑定值,就可以设置样式的字体颜色了,如下:

刷新浏览器,如下:

函数简写[4]
在很多时候,你可能想在 bind
和 update
时触发相同行为,而不关心其它的钩子。比如这样写:
Vue.directive('color-swatch', function (el, binding) {
el.style.backgroundColor = binding.value
})
这是全局自定义指令的写法, 下面这是局部自定义指令的写法,如下:
首先绑定一个自定义指令v-fontsize
在元素上。

然后定义简写的自定义指令,如下:

directives: {
'fontsize': function (el, binding) { // 注意:这个 function 等同于 把 代码写到了 bind 和 update 中去
el.style.fontSize = parseInt(binding.value) + 'px'
},
'focus': {
bind: function (el,binding) { // 每当指令绑定到元素上的时候,会立即执行这个 bind 函数,只执行一次
// 注意:在每个 函数中,第一个参数,永远是 el ,表示 被绑定了指令的那个元素,这个 el 参数,是一个原生的JS对象
// 在元素 刚绑定了指令的时候,还没有 插入到 DOM中去,这时候,调用 focus 方法没有作用
// 因为,一个元素,只有插入DOM之后,才能获取焦点
// el.focus()
...
浏览器显示效果如下:

Reference
简介: https://cn.vuejs.org/v2/guide/custom-directive.html#%E7%AE%80%E4%BB%8B
[2]
钩子函数: https://cn.vuejs.org/v2/guide/custom-directive.html#%E9%92%A9%E5%AD%90%E5%87%BD%E6%95%B0
[3]
钩子函数参数: https://cn.vuejs.org/v2/guide/custom-directive.html#%E9%92%A9%E5%AD%90%E5%87%BD%E6%95%B0%E5%8F%82%E6%95%B0
[4]
函数简写: https://cn.vuejs.org/v2/guide/custom-directive.html#%E5%87%BD%E6%95%B0%E7%AE%80%E5%86%99
交流QQ群:

点击下面,查看更多Vue系列文章
原文始发于微信公众号(海洋的渔夫):19. Vue 自定义指令
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/32100.html