Vue 进阶系列丨自定义指令

9c7186439b822fbbedbd110579b143e6.png

Vue 进阶系列教程将在本号持续发布,一起查漏补缺学个痛快!若您有遇到其它相关问题,非常欢迎在评论中留言讨论,达到帮助更多人的目的。若感本文对您有所帮助请点个赞吧!


2013年7月28日,尤雨溪第一次在 GItHub 上为 Vue.js 提交代码;2015年10月26日,Vue.js 1.0.0版本发布;2016年10月1日,Vue.js 2.0发布。

最早的 Vue.js 只做视图层,没有路由, 没有状态管理,也没有官方的构建工具,只有一个库,放到网页里就可以直接用了。

后来,Vue.js 慢慢开始加入了一些官方的辅助工具,比如路由(Router)、状态管理方案(Vuex)和构建工具(Vue-cli)等。此时,Vue.js 的定位是:The Progressive Framework。翻译成中文,就是渐进式框架。

Vue.js2.0 引入了很多特性,比如虚拟 DOM,支持 JSX 和 TypeScript,支持流式服务端渲染,提供了跨平台的能力等。Vue.js 在国内的用户有阿里巴巴、百度、腾讯、新浪、网易、滴滴出行、360、美团等等。

Vue 已是一名前端工程师必备的技能,现在就让我们开始深入学习 Vue.js 内部的核心技术原理吧!


自定义指令

类似于 v-if、v-for 一样,Vue.js 向用户提供了实现自定义指令的功能。你可以通过指令对普通 DOM 元素进行底层操作,比如修改元素的样式、元素的默认效果等。我们先举一个简单的例子,让大家对自定义指令有一个更直观的认识。

<p v-color>Hfun Fly</p>


directives:{
 color: {
    inserted(el) {
      el.style.color = '#f00'
    }
 }
}

效果如下:

d12d9c3b6950480b894e865bb793935c.png

可以看到,我们的指令生效了,“Hfun Fly” 变成了红色。代码中的 insert 是指令执行过程中的一个钩子函数,将在当前指令所绑定的元素插入到父节点时被调用,参数 el 是绑定的元素的 DOM 对象。下面我们进一步看一下自定义指令所经历的各个生命周期钩子。


钩子函数

  • bind :只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。

  • inserted:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。

  • update:所在组件的 VNode 更新时调用,但是可能发生在其子VNode更新之前。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新 (详细的钩子函数参数见下)。

  • componentUpdated:指令所在组件的 VNode 及其子 VNode 全部更新后调用。

  • unbind:只调用一次,指令与元素解绑时调用。


钩子函数参数

每个钩子函数都接受4个参数,分别是 el、binding、vnode 和 oldVnode,下面是官方文档给出的解释。

  • el:指令所绑定的元素,可以用来直接操作 DOM。

  • binding:一个对象,包含以下 property:

    • 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 编译生成的虚拟节点。

  • oldVnode:上一个虚拟节点,仅在 update 和 componentUpdated 钩子中可用

可能 binding 钩子函数里面的参数看起来不是很清楚,下面我们用一个例子来加深一下对上面参数的理解。

<p v-color:foo.a.b="test">Hfun Fly</p>


directives:{
  color: {
      update(el,binding,vnode,oldVnode) {
        console.log(binding)
      }
  }
},
-------------------------------输出-------------------------------
{
    "name": "color",  //  指令名
    "value": "hahaha", //  update之后,绑定的变量真实值
    "oldValue": "hahaha",  //  update之前,绑定的变量真实值
    "expression": "test",  // 绑定的变量名
    "arg": "foo", // 绑定的指令的参数
    "modifiers": {
        "a": true,
        "b": true


    }, // 绑定的修饰符对象
}

根据传入参数的不同,我们可以将上方里例子改进一下,根据用户传入的参数的不同,动态改变字体样式。改造后代码如下:

<p v-color="'#00ff00'">Hfun Fly</p>
<p v-color="'#0000ff'">Hfun Fly</p>
<p v-color="'#ff0000'">Hfun Fly</p>


directives:{
 color: {
    inserted(el) {
      el.style.color = binding.value
    }
 }
}

效果如下:

aaaa2213f12ac991114ec80581d0f2be.png

注意:上方代码中 v-color="'#00ff00'" 中绑定的是一个字符串,如果内部没有带引号,默认绑定的是变量,变量我们只需要在 data 中声明即可。

比如我们可以动态绑定指令的参数,举个简单的小例子:

<p v-color[foo]>Hfun Fly</p>


directives:{
 color: {
    inserted(el,binding) {
      console.log(binding.arg) // a
    }
 }
},
data(){
  return{
    foo:'a'
  }
}

我们可以通过改变 foo 的值,达到动态绑定自定义指令参数的效果。在钩子函数中,通过指令参数可以动态的修改绑定元素的 DOM 元素。


函数简写

在很多时候,你可能想在 bind 和 update 时触发相同行为,而不关心其它的钩子。那么就可以省略钩子函数的步骤了。

<p v-color>Hfun Fly</p>


directives:{
 color(el) {
  el.style.color = 'red'
 }
},

对象字面量

如果指令需要多个值,可以传入一个 JavaScript 对象字面量。

<p v-color="{ color: 'red', text: 'hello' }">Hfun Fly</p>


directives:{
 color(el,binding) {
    console.log(binding.value.color) //  "red"
    console.log(binding.value.text)  //  "hello"
 }
},

全局注册和局部注册

对于自定义指令,我们既可以全局注册,也可以局部注册。对于全局注册我们只需要在 main.js 里定义,就可以在所有页面中使用了。全局注册语法如下:

Vue.directive('color', {
   inserted: function(el) {
        el.style.color = 'red'
    } 
});

局部注册就像上方例子中的一样,在每一个文件中通过定义,只能在当前文件中使用。局部注册语法如下:

<p v-color>Hfun Fly</p>


directives:{
 color(el) {
  el.style.color = 'red'
 }
},

Vue 进阶系列教程将在本号持续发布,一起查漏补缺学个痛快!若您有遇到其它相关问题,非常欢迎在评论中留言讨论,达到帮助更多人的目的。若感本文对您有所帮助请点个赞吧!

67265088a41c838a2831c73dff984ef7.png

叶阳辉

HFun 前端攻城狮

往期精彩:

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值