Vue.JS入门教程之自定义指令


Posted in Javascript onDecember 08, 2016

基础

Vue.js 允许你注册自定义指令,实质上是让你教 Vue 一些新技巧:怎样将数据的变化映射到 DOM 的行为。你可以使用Vue.directive(id, definition)的方法传入指令id和定义对象来注册一个全局自定义指令。定义对象需要提供一些钩子函数(全部可选):

  • bind: 仅调用一次,当指令第一次绑定元素的时候。
  • update: 第一次是紧跟在 bind 之后调用,获得的参数是绑定的初始值;以后每当绑定的值发生变化就会被调用,获得新值与旧值两个参数。
  • unbind:仅调用一次,当指令解绑元素的时候。

例子:

Vue.directive('my-directive', {
 bind: function () {
 // 做绑定的准备工作
 // 比如添加事件监听器,或是其他只需要执行一次的复杂操作
 },
 update: function (newValue, oldValue) {
 // 根据获得的新值执行对应的更新
 // 对于初始值也会被调用一次
 },
 unbind: function () {
 // 做清理工作
 // 比如移除在 bind() 中添加的事件监听器
 }
})

一旦注册好自定义指令,你就可以在 Vue.js 模板中像这样来使用它(需要添加 Vue.js 的指令前缀,默认为 v-):

<div v-my-directive="someValue"></div>

如果你只需要 update 函数,你可以只传入一个函数,而不用传定义对象:

Vue.directive('my-directive', function (value) {
 // 这个函数会被作为 update() 函数使用
})

所有的钩子函数会被复制到实际的指令对象中,而这个指令对象将会是所有钩子函数的this
上下文环境。指令对象上暴露了一些有用的公开属性:

el: 指令绑定的元素
vm: 拥有该指令的上下文 ViewModel
expression: 指令的表达式,不包括参数和过滤器
arg: 指令的参数
raw: 未被解析的原始表达式
name: 不带前缀的指令名

这些属性是只读的,不要修改它们。你也可以给指令对象附加自定义的属性,但是注意不要覆盖已有的内部属性。

使用指令对象属性的示例:

 

<!DOCTYPE html>
<html>
<head lang="en">
 <meta charset="UTF-8">
 <title></title>
 <script src="http://cdnjs.cloudflare.com/ajax/libs/vue/0.12.16/vue.min.js"></script>
</head>
<body>
<div id="demo" v-demo-directive="LightSlateGray : msg"></div>

<script>
 Vue.directive('demoDirective', {
  bind: function () {
   this.el.style.color = '#fff'
   this.el.style.backgroundColor = this.arg
  },
  update: function (value) {
   this.el.innerHTML =
     'name - '  + this.name + '<br>' +
     'raw - '  + this.raw + '<br>' +
     'expression - ' + this.expression + '<br>' +
     'argument - ' + this.arg + '<br>' +
     'value - '  + value
  }
 });
 var demo = new Vue({
  el: '#demo',
  data: {
   msg: 'hello!'
  }
 })

</script>
</body>
</html>

多重从句

同一个特性内部,逗号分隔的多个从句将被绑定为多个指令实例。在下面的例子中,指令会被创建和调用两次:

<div v-demo="color: 'white', text: 'hello!'"></div>

如果想要用单个指令实例处理多个参数,可以利用字面量对象作为表达式:

<div v-demo="{color: 'white', text: 'hello!'}"></div>

Vue.directive('demo', function (value) {
 console.log(value) // Object {color: 'white', text: 'hello!'}
})

字面指令

如果在创建自定义指令的时候传入 isLiteral: true ,那么特性值就会被看成直接字符串,并被赋值给该指令的 expression。字面指令不会试图建立数据监视。
例子:

<div v-literal-dir="foo"></div>

Vue.directive('literal-dir', {
 isLiteral: true,
 bind: function () {
 console.log(this.expression) // 'foo'
 }
})

动态字面指令

然而,在字面指令含有 Mustache 标签的情形下,指令的行为如下:

指令实例会有一个属性,this._isDynamicLiteral被设为true;

如果没有提供update函数,Mustache 表达式只会被求值一次,并将该值赋给this.expression。不会对表达式进行数据监视。

如果提供了update函数,指令将会为表达式建立一个数据监视,并且在计算结果变化的时候调用update。

双向指令

如果你的指令想向 Vue 实例写回数据,你需要传入 twoWay: true 。该选项允许在指令中使用 this.set(value)。

Vue.directive('example', {
 twoWay: true,
 bind: function () {
 this.handler = function () {
  // 把数据写回 vm
  // 如果指令这样绑定 v-example="a.b.c",
  // 这里将会给 `vm.a.b.c` 赋值
  this.set(this.el.value)
 }.bind(this)
 this.el.addEventListener('input', this.handler)
 },
 unbind: function () {
 this.el.removeEventListener('input', this.handler)
 }
})

内联语句

传入 acceptStatement: true 可以让自定义指令像 v-on 一样接受内联语句:

<div v-my-directive="a++"></div>

Vue.directive('my-directive', {
 acceptStatement: true,
 update: function (fn) {
 // the passed in value is a function which when called,
 // will execute the "a++" statement in the owner vm's
 // scope.
 }
})

但是请明智地使用此功能,因为通常我们希望避免在模板中产生副作用。

深度数据观察

如果你希望在一个对象上使用自定义指令,并且当对象内部嵌套的属性发生变化时也能够触发指令的 update 函数,那么你就要在指令的定义中传入 deep: true。

<div v-my-directive="obj"></div>

Vue.directive('my-directive', {
 deep: true,
 update: function (obj) {
 // 当 obj 内部嵌套的属性变化时也会调用此函数
 }
})

指令优先级

你可以选择给指令提供一个优先级数(默认是0)。同一个元素上优先级越高的指令会比其他的指令处理得早一些。优先级一样的指令会按照其在元素特性列表中出现的顺序依次处理,但是不能保证这个顺序在不同的浏览器中是一致的。

通常来说作为用户,你并不需要关心内置指令的优先级,如果你感兴趣的话,可以参阅源码。逻辑控制指令 v-repeat, v-if 被视为 “终结性指令”,它们在编译过程中始终拥有最高的优先级。

元素指令

有时候,我们可能想要我们的指令可以以自定义元素的形式被使用,而不是作为一个特性。这与 Angular 的 E 类指令的概念非常相似。元素指令可以看做是一个轻量的自定义组件(后面会讲到)。你可以像下面这样注册一个自定义的元素指令:

Vue.elementDirective('my-directive', {
 // 和普通指令的 API 一致
 bind: function () {
 // 对 this.el 进行操作...
 }
})

使用时我们不再用这样的写法:

<div v-my-directive></div>

而是写成:

<my-directive></my-directive>
元素指令不能接受参数或表达式,但是它可以读取元素的特性,来决定它的行为。与通常的指令有个很大的不同,元素指令是终结性的,这意味着,一旦 Vue 遇到一个元素指令,它将跳过对该元素和其子元素的编译 - 即只有该元素指令本身可以操作该元素及其子元素。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
jQuery中add实现同时选择两个id对象
Oct 22 Javascript
用js通过url传参把数据从一个页面传到另一个页面
Sep 01 Javascript
js数组去重的方法汇总
Jul 29 Javascript
JavaScript编程中window的location与history对象详解
Oct 26 Javascript
基于Bootstrap实现Material Design风格表单插件 附源码下载
Apr 18 Javascript
JS基于递归实现倒计时效果的方法
Nov 26 Javascript
jQuery.Validate表单验证插件的使用示例详解
Jan 04 Javascript
彻底学会Angular.js中的transclusion
Mar 12 Javascript
jQuery编写textarea输入字数限制代码
Mar 23 jQuery
详解bootstrap用dropdown-menu实现上下文菜单
Sep 22 Javascript
vue异步加载高德地图的实现
Jun 19 Javascript
微信小程序自定义头部导航栏(组件化)
Nov 15 Javascript
微信公众号开发 自定义菜单跳转页面并获取用户信息实例详解
Dec 08 #Javascript
node.js学习之交互式解释器REPL详解
Dec 08 #Javascript
JavaScript正则表达式小结(test|match|search|replace|split|exec)
Dec 08 #Javascript
JS中用childNodes获取子元素换行会产生一个子元素
Dec 08 #Javascript
微信公众号 摇一摇周边功能开发
Dec 08 #Javascript
Vue概念及常见命令介绍(1)
Dec 08 #Javascript
Jquery给当前页或者跳转后页面的导航栏添加选中后样式的实例
Dec 08 #Javascript
You might like
人族 TERRAN 概述
2020/03/14 星际争霸
深入理解用mysql_fetch_row()以数组的形式返回查询结果
2013/06/05 PHP
destoon实现调用图文新闻的方法
2014/08/21 PHP
php判断文件上传类型及过滤不安全数据的方法
2014/12/17 PHP
php将print_r处理后的数据还原为原始数组的解决方法
2016/11/02 PHP
浅析PHP中的 inet_pton 网络函数
2019/12/16 PHP
通过JS获取用户本地图片路径并显示的代码
2012/02/16 Javascript
JQUERY 获取IFrame中对象及获取其父窗口中对象示例
2013/08/19 Javascript
node.js中的http.request.end方法使用说明
2014/12/10 Javascript
jquery实现界面无刷新加载登陆注册
2016/07/30 Javascript
JS实现中国公民身份证号码有效性验证
2017/02/20 Javascript
关于vuejs中v-if和v-show的区别及v-show不起作用问题
2018/03/26 Javascript
小程序云开发部署攻略(图文教程)
2018/10/30 Javascript
微信小程序实现留言板(Storage)
2018/11/02 Javascript
详解如何用webpack4从零开始构建react开发环境
2019/01/27 Javascript
video.js添加自定义组件的方法
2020/12/09 Javascript
Python的加密模块md5、sha、crypt使用实例
2014/09/28 Python
Python使用random和tertools模块解一些经典概率问题
2015/01/28 Python
Python操作Excel之xlsx文件
2017/03/24 Python
详解python while 函数及while和for的区别
2018/09/07 Python
基于Python实现迪杰斯特拉和弗洛伊德算法
2020/05/27 Python
Python Django基础二之URL路由系统
2019/07/18 Python
10分钟教你用python动画演示深度优先算法搜寻逃出迷宫的路径
2019/08/12 Python
Python xml、字典、json、类四种数据类型如何实现互相转换
2020/05/27 Python
Python中flatten( ),matrix.A用法说明
2020/07/05 Python
在python中对于bool布尔值的取反操作
2020/12/11 Python
在vscode中启动conda虚拟环境的思路详解
2020/12/25 Python
css3实现一个div设置多张背景图片及background-image属性实例演示
2017/08/10 HTML / CSS
CSS Grid布局教程之网格单元格布局
2014/12/30 HTML / CSS
html5 video标签屏蔽右键视频另存为的js代码
2013/11/12 HTML / CSS
HTML5 Canvas实现图片缩放、翻转、颜色渐变的代码示例
2016/02/28 HTML / CSS
复古风格的女装和装饰品:ModCloth
2017/12/29 全球购物
2014年医学生毕业自我鉴定
2014/03/26 职场文书
乡镇党委书记第三阶段个人整改措施
2014/09/16 职场文书
幼儿园教师管理制度
2015/08/05 职场文书
聘任书范文大全
2015/09/21 职场文书