前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >23. Vue 自定义指令

23. Vue 自定义指令

作者头像
Devops海洋的渔夫
发布2020-03-25 17:57:20
1.2K0
发布2020-03-25 17:57:20
举报
文章被收录于专栏:Devops专栏Devops专栏

需求

可以看到上面的输入框在刷新页面并没有进行自动聚焦,那么这时候可以使用自定义一个focus()方法来处理。 还有能否在刷新页面的时候,可以设置value在文本框中以及设置字体颜色呢? 能否进而通过传参的方式设置字体颜色呢?

这些都可以基于Vue的自定义指令来实现。

简介

除了核心功能默认内置的指令 (v-modelv-show),Vue 也允许注册自定义指令。注意,在 Vue2.0 中,代码复用和抽象的主要形式是组件。然而,有的情况下,你仍然需要对普通 DOM 元素进行底层操作,这时候就会用到自定义指令。

对于上面的需求,则需要自定义一个聚焦的focust方法。

当页面加载时,该元素将获得焦点 (注意:autofocus 在移动版 Safari 上不工作)。事实上,只要你在打开这个页面后还没点击过任何内容,这个输入框就应当还是处于聚焦状态。现在让我们用指令来实现这个功能:

代码语言:javascript
复制
// 注册一个全局自定义指令 `v-focus`
Vue.directive('focus', {
  // 当被绑定的元素插入到 DOM 中时……
  inserted: function (el) {
    // 聚焦元素
    el.focus()
  }
})

如果想注册局部指令,组件中也接受一个 directives 的选项:

代码语言:javascript
复制
directives: {
  focus: {
    // 指令的定义
    inserted: function (el) {
      el.focus()
    }
  }
}

然后你可以在模板中任何元素上使用新的 v-focus 属性,如下:

代码语言:javascript
复制
<input v-focus>

在上面定义自定义指令中,使用了inserted这个钩子函数,另外还有更多的钩子函数。

钩子函数

一个指令定义对象可以提供如下几个钩子函数 (均为可选):

  • bind:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。
  • inserted:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。
  • update:所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新。
  • componentUpdated:指令所在组件的 VNode 及其子 VNode 全部更新后调用。
  • unbind:只调用一次,指令与元素解绑时调用。

bind: 在列表中初始化输入框的值以及字体样式

bind:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。 一般bind只会去处理元素的样式、值等属性,不会去处理js函数,因为有很多js函数需要插入dom内存中才可以处理,而bind在之前,导致js函数执行失败。可以考虑bind是执行在window.onload之前的行为。

代码语言:javascript
复制
        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钩子函数的时候,写死了字体颜色,那么能否通过参数化,将参数传递进去呢?

接下来我们来看一下钩子函数的参数 (即 elbindingvnodeoldVnode)。

钩子函数参数

指令钩子函数会被传入以下参数:

  • el:指令所绑定的元素,可以用来直接操作 DOM 。
  • binding:一个对象,包含以下属性:
    • name:指令名,不包括 v- 前缀。
    • value:指令的绑定值,例如:v-my-directive="1 + 1" 中,绑定值为 2
    • oldValue:指令绑定的前一个值,仅在 updatecomponentUpdated 钩子中可用。无论值是否改变都可用。
    • 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:上一个虚拟节点,仅在 updatecomponentUpdated 钩子中可用。

除了 el 之外,其它参数都应该是只读的,切勿进行修改。如果需要在钩子之间共享数据,建议通过元素的 dataset 来进行。

看了上面官网介绍的这些钩子函数参数我是比较迷糊的,不过,没关系。下面写个示例打印一下信息,就知道大概是怎么回事了。

打印钩子函数的参数信息

这个打印信息,我主要打印这几个常用的参数,用来刚才上面如何设置输入框的字体颜色。

  • binding:一个对象,包含以下属性:
    • name:指令名,不包括 v- 前缀。
    • value:指令的绑定值,例如:v-my-directive="1 + 1" 中,绑定值为 2
    • expression:字符串形式的指令表达式。例如 v-my-directive="1 + 1" 中,表达式为 "1 + 1"

首先,我给自定义命令设置一个绑定的值,如下:

代码语言:javascript
复制
<input v-focus="'green'"

注意:我设置里面的是一个字符串'green',因为后续我要用来设置样式。

首先打印一下这三个参数会显示什么内容来看看。

浏览器打印信息如下:

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

刷新浏览器,如下:

函数简写

在很多时候,你可能想在 bindupdate 时触发相同行为,而不关心其它的钩子。比如这样写:

代码语言:javascript
复制
Vue.directive('color-swatch', function (el, binding) {
  el.style.backgroundColor = binding.value
})

这是全局自定义指令的写法, 下面这是局部自定义指令的写法,如下:

首先绑定一个自定义指令v-fontsize在元素上。

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

代码语言:javascript
复制
        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()
        ...

浏览器显示效果如下:

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 需求
  • 简介
  • 钩子函数
    • bind: 在列表中初始化输入框的值以及字体样式
      • inserted:在列表中实现该聚焦focus需求
      • 钩子函数参数
        • 打印钩子函数的参数信息
        • 函数简写
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档