Vue 通过自定义指令回顾v-内置指令(小结)


Posted in Javascript onSeptember 03, 2018

Vue.js 的各种指令(Directives)更加方便我们去数据驱动 DOM,例如 v-bind、v-on、v-model、v-if、v-for、v-once 等内置指令,这些指令的职责就是当表达式改变时将某些行为应用到 DOM 上,尽量不去操作增删改 DOM。通过了解如何去自定义指令,可以想象内置指令是如何完成的。

内置指令

指令名称 描述 使用
v-model 绑定数据
v-text 输出文本,不能解析标签
v-html 输出文本,可解析标签 /p>
v-once 只绑定一次数据 {{message}}
v-bind 绑定属性
v-if 控制是否显示容器 值转为布尔为false时 注释该容器,反之显示
v-show 控制是否显容器,改变的时display:none/block
v-for 循环遍历数组、对象 {{val}}
v-cloak 在还没有执行到vue代码的时候隐藏元素,可解决‘闪烁'问题 {{message}}

自定义指令

在需要特殊功能时,使用自定义指令对 DOM 进行底层操作

注册

自定义指令的注册分为全局注册和局部注册,类似组件的注册,只是方法名为 directive,写法如下:

// 全局注册 自定义指令
Vue.directive(‘mydir',{
  // 指令选项
});
// 全局注册 自定义指令函数
Vue.directive('mydir', function () {
 // 这里将会被 `bind` 和 `update` 调用
})
// 局部注册(只针对组件内元素)
export default {
  directives: {
    mydir: {
      // 指令选项
    }
  }
}

需要注意的是:Vue.directive( ) 注册指令要在实例初始化 new Vue( ) 之前才能全局注册指令。定义指令时驼峰式写法会报错,所以一般小写。

指令选项

自定义指令的选项是由几个钩子函数(可选)组成,可以根据需求选择不同的钩子,例如使用全局注册一个指令时:

Vue.directive('mydir', {
 bind: function () {
  // 只调用一次,指令第一次绑定到元素时调用,用于在绑定元素时执行一次的初始化动作。
  },
 update: function () {
  // 第一次是紧跟在 bind 之后调用,获得的参数是绑定的初始值,
  // 之后被绑定元素所在的模板更新时调用,而不论绑定值是否变化,可以忽略不必要的模板更新。  
  }, 
 inserted: function () {
  // 被绑定元素插入父节点时调用(父节点存在即可调用,不必存在于 document 中)。
  },
 componentUpdated: function () {
  // 被绑定元素所在模板完成一次更新周期时调用。
  },
 unbind: function () {
  // 只调用一次, 指令与元素解绑时调用。
  }
})

以上每个钩子函数都有几个参数可用:

  1. el:指令所绑定的元素,可以用来直接操作 DOM;
  2. binding:包含指令信息的一个对象;
  3. vnode:Vue 编译的生成虚拟节点;
  4. oldVnode:上一次的虚拟节点,仅在update和componentUpdated钩子函数中可用。

示例

// 一个带自定义指令的元素
<div v-mytest:foo.m1.m2="1+1">MyDirective</div>

// 部分 JS 代码
export default {
  directives:{
   mytest: {
    bind: function (el, binding, vnode) {
     console.log(el)
     console.log(binding)
     console.log(vnode)
    }
   }
  }
}

控制台输出截图:

Vue 通过自定义指令回顾v-内置指令(小结)

其中对于 binding 对象输出的属性有:

  1. rawName: "v-mytest:foo.m1.m2" // 自定义指令
  2. name: "mytest" // 指令名称
  3. arg: "foo" // 指令的参数
  4. modifiers: {m1: true, m2: true} // 指令的修饰符
  5. expression: "1+1" // 指令绑定值的字符串形式
  6. value: 2 // 指令的绑定值

v-bind || : 绑定属性

Vue 内置指令 v-bind 用于动态更新 HTML 元素属性,使用 v-bind:someAttr = "someData"或者语法糖 :someAttr = "someData"就可以在 someData 改变时更新绑定的 someAttr 属性。

基本用法

绑定单一的属性值

<a :href="url" rel="external nofollow" rel="external nofollow" :id="linkID">链接</a>

测试 data 如下:

// js
data : {
  url: 'https://www.baidu.com/',
  linkID : 'myid'
}

元素渲染输出:

<a href="https://www.baidu.com/" rel="external nofollow" rel="external nofollow" id="myid">链接</a>

对象语法

v-bind 最常用的是绑定 class 或 style 属性来动态改变样式。例如可以给 :class 设置一个对象来动态切换 class 的值:

<!-- class 绑定 -->
<div :class="{colorRed: isRed}"></div>

当 isRed:true 时渲染输出:

<div class="colorRed"></div>

对象中可以传入多个属性值来动态切换 class:

<!-- class 绑定,传入多个属性 -->
<div :class="{ classA: isA, classB: isB }">

当 isA、isB 变化时 classA、classB 会动态更新,当都为 true 时显然渲染结果为:

<div class="classA classB"></div>

同理对于 style 可以传入对象属性,并且可以使用字符串拼接:

<!-- style 绑定 -->
<div :style="{ fontSize: size + 'px' }"></div>

对于元素中的各个对象可以统一用 v-bind 绑定:

<!-- 绑定一个有属性的对象 -->
<div v-bind="{ id: someProp, 'other-attr': otherProp }"></div>

数组语法

class 可以传入多值,给 :class 绑定一个数组就可以使用 class 列表

<div :class="[activeA, activeB]"></div>

例如当 {activeA: 'class1', activeB: 'class2'} 时渲染结果为:

<div class="class1 class2"></div>

还可以在数组语法中使用三元表达式切换 class,例如:

<div :class="[isA ? activeA : '', activeB]">

在 class 有多个条件时使用三元表达式比较繁琐,可以在数组语法中使用对象语法:

<div :class="[{activeA: isA}, activeB]">

修饰符

v-bind 的修饰符很少,API 中只提供.prop、.camel和.sync,并且多用于组件,使用方式示例:

<!-- 通过 prop 修饰符绑定 DOM 属性 (property) -->
<div v-bind:text-content.prop="text"></div>

<!-- .camel 修饰符(2.1.0+)将 v-bind 属性名称 kebab-case 驼峰化为 camelCase -->
<svg :view-box.camel="viewBox"></svg>

<!-- .sync 修饰符(2.3.0+) 语法糖,会扩展成一个更新父组件绑定值的 v-on 侦听器-->
<text-document v-bind:title.sync="doc.title"></text-document>
<!-- 批量绑定,将 doc 对象中的每一个属性 (如 title) 都作独立的 prop ,各自添加 v-on 监听器-->
<text-document v-bind.sync="doc"></text-document>

v-on || @ 监听事件

v-on 用于动态绑定事件监听器,使用 v-on:someEvent = "someFunction"或者语法糖 @someEvent = "someFunction"就可以监听 someEvent 进行交互。

基本用法

@someEvent 调用的方法名后面可以不跟(),例如:

<a :href="url" rel="external nofollow" rel="external nofollow" :id="linkID">链接</a>
<!-- 监听一个事件 -->
<button @click="changeFun">change button</button>

可以在 methods 中添加函数:

// 部分 JS 代码
methods :{
 changeFun : function () {
  this.linkID = 'changeID' // 指向当前组件本身
 }
}

点击 button 按钮后 a 元素的 id 改变:

<a href="https://www.baidu.com/" rel="external nofollow" rel="external nofollow" id="changeID">链接</a>

当然 v-on 还可以使用对象语法监听多个事件:

<!-- v2.4.0+ -->
<button v-on="{ mousedown: doThis, mouseup: doThat }"></button>

对于在 HTML 元素上监听的事件,当 ViewModel 销毁时,所有的事件处理器会自动删除,无需自己清理。

修饰符

Vue 可以将原生事件对象参数 event 传入事件方法中,并提供了特殊变量$event用来访问元素 DOM 事件。此外可以通过一些事件修饰符来实现特定的事件,如 .stop、.prevent、.capture、.once 等,常用的使用示例:

<!-- 停止单击事件冒泡,调用 event.stopPropagation()-->
<button @click.stop="doThis"></button>

<!-- 阻止默认行为,调用 event.preventDefault() -->
<button @submit.prevent="doThis"></button>

<!-- 添加事件侦听器时使用 capture 事件捕获模式 -->
<button @click.capture="doThis"></button>

<!-- 点击回调只会触发一次 -->
<button @click.once="doThis"></button>

<!-- 只当点击鼠标左键时触发(2.2.0) -->
<button @click.left="doThis"></button>

<!-- 串联修饰符 -->
<button @click.stop.prevent="doThis"></button>

此外,v-on 还提供按键修饰符来监听键盘事件,键值为 .keyCode,常用有.entry、.delete、.tab、.esc、.space、.down等,如下:

<!-- 只有在 `keyCode` 是 5 时调用 `vm.submit()` -->
<input v-on:keyup.5="submit">

<!-- 为重要的 keyCode 如 enter 提供别名-->
<input v-on:keyup.enter="submit">

<!-- 缩写语法 -->
<input @keyup.enter="submit">

此外还有系统修饰符监听键盘事件,不同的系统其键盘/系统修饰符不一样。这些按键修饰符可以任意组合使用。

v-if、v-show 条件渲染

条件渲染 v-if 根据表达式的值的真假条件渲染元素,在表达式为真时渲染,为假时移除。

<p v-if="status === 1">当 status 为 1 时显示此行</p>

<p v-else-if="status === 1">当 status 为 2 时显示此行</p>

<p v-else>其它情况默认显示此行</p>

v-show 也是条件渲染,但只切换元素的 CSS 属性 display,无论条件真假都会被编译,相比于 v-if 更适用于频繁切换场景。

<p v-show="status === 1">当 status 为 1 时显示此行</p>

当 data: {status: 2} 时隐藏,但依旧会被编译,渲染结果为:

<p style="display: none;">当 status 为 1 时显示此行</p>

显然在 Vue.js 内置的 <template> 元素上可以使用 v-if,但不能使用 v-show,可以思考下为什么。

v-for 列表渲染

列表渲染指令 v-for 常用于数组遍历或枚举一个对象的循环显示,必须结合 in 使用特定语法 alias in expression 为当前遍历的元素提供别名:

<!-- 遍历一个数组 -->
<div v-for="item in items">{{ item.text }}</div>

<!-- 提供第二个的参数为数组的索引 -->
<div v-for="(item, index) in items">{{ index }} - {{ item.text }}</div>

<!-- 遍历对象属性 -->
<div v-for="value in object">{{ value }}</div>

<!-- 提供第二个可选的参数:对象的键名 -->
<div v-for="(value, key) in object">{{ key }}: {{ value }}</div>

<!-- 提供第三个的可选参数:对象的索引 -->
<div v-for="(value, key, index) in object">{{ index }}. {{ key }}: {{ value }}</div>

可以用 of 替代 in 作为分隔符

当 v-for 和 v-if 在同一节点一起使用时,v-for 的优先级比 v-if 更高。

v-model 表单控件双向绑定

v-model 其实也是一个特殊的语法糖,其实实现的数据双向绑定也可用v-bind和v-on实现,但v-model在不同表单上会有更加智能的处理。

文本框

经典的使用案例是对<input>、<textarea>文本框的双向数据绑定:

<!-- 输入框 -->
<input type="text" v-model="message" placeholder="edit me">
<!-- 文本域 -->
<textarea v-model="message" placeholder="edit me"></textarea>
<!-- 实时更新 -->
<p>Message is: {{ message }}</p>

动态选择

对于单选按钮,复选框及选择框的选项,v-model配合 Vue 实例的数据作为value属性值实现不同效果,即会忽略所有表单元素的 value、checked、selected 特性的值。

<!--单选按钮的互斥效果-->
<div id="example-radio">
 <input type="radio" id="one" value="One" v-model="picked">
 <label for="one">One</label>
 
 <input type="radio" id="two" value="Two" v-model="picked">
 <label for="two">Two</label>
 
 <!-- picked 显示的是 value 的值 -->
 <p>Picked: {{ picked }}</p>
</div>

<!--多选按钮-->
<div id='example-checkbox'>
 <input type="checkbox" id="one" value="One" v-model="checkedNames">
 <label for="jack">Jack</label>
 <input type="checkbox" id="two" value="Two" v-model="checkedNames">
 <label for="john">John</label>

  <!-- Checked 显示的是 value 组成的数组 -->
 <p>Checked: {{ checkedNames }}</p>
</div>

修饰符

v-model的修饰符的使用限制在<input>、<select>、<textarea> 和组件。

  1. .lazy - 取代 input 监听 change 事件
  2. .number - 输入字符串转为数字
  3. .trim - 输入首尾空格过滤

v-pre、v-cloak、v-once

这三个指令的共同点是无需表达式,用法如下:

<!-- 不显示未编译的标签直到实例初始化完 -->
<div v-cloak>{{ message }}</div>
<!-- 需要配合 CSS 隐藏样式 [v-cloak]{ display: none;}-->

<!-- 只渲染一次,随后的渲染将被视为静态内容并跳过 -->
<div v-once>{{ message }}</div>

<!-- 不会被编译,直接显示显示原始{{ }}标签 -->
<div v-pre>{{ message }}</div>

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

Javascript 相关文章推荐
JS应用正则表达式转换大小写示例
Sep 18 Javascript
jQuery带时间的日期控件代码分享
Aug 26 Javascript
Vuex2.0+Vue2.0构建备忘录应用实践
Nov 30 Javascript
Swiper 4.x 使用方法(移动端网站的内容触摸滑动)
May 17 Javascript
vue form 表单提交后刷新页面的方法
Sep 04 Javascript
在vue项目中集成graphql(vue-ApolloClient)
Sep 08 Javascript
JavaScript实现表单注册、表单验证、运算符功能
Oct 15 Javascript
vue 使用鼠标滚动加载数据的例子
Oct 31 Javascript
24行JavaScript代码实现Redux的方法实例
Nov 17 Javascript
vue 动态表单开发方法案例详解
Dec 02 Javascript
react实现移动端下拉菜单的示例代码
Jan 16 Javascript
浅析vue cli3 封装Svgicon组件正确姿势(推荐)
Apr 27 Javascript
JavaScript日期工具类DateUtils定义与用法示例
Sep 03 #Javascript
Angular5中状态管理的实现
Sep 03 #Javascript
JavaScript创建对象方法实例小结
Sep 03 #Javascript
vue自定义底部导航栏Tabbar的实现代码
Sep 03 #Javascript
解决vue单页路由跳转后scrollTop的问题
Sep 03 #Javascript
webpack4 SCSS提取和懒加载的示例
Sep 03 #Javascript
vue自定v-model实现表单数据双向绑定问题
Sep 03 #Javascript
You might like
生成卡号php代码
2008/04/09 PHP
php操作excel文件 基于phpexcel
2010/07/02 PHP
比较完整的微信开发php代码
2016/08/02 PHP
yii的入口文件index.php中为什么会有这两句
2016/08/04 PHP
php根据年月获取当月天数及日期数组的方法
2016/11/30 PHP
PHPMAILER实现PHP发邮件功能
2018/04/18 PHP
Jquery操作radio的简单实例
2014/01/06 Javascript
window.location.href IE下跳转失效的解决方法
2014/03/27 Javascript
JavaScript模块化开发之SeaJS
2015/12/13 Javascript
JS动态改变浏览器标题的方法
2016/04/06 Javascript
封装获取dom元素的简单实例
2016/07/08 Javascript
NodeJS处理Express中异步错误
2017/03/26 NodeJs
Three.js基础学习之场景对象
2017/09/27 Javascript
JS实现的简单四则运算计算器功能示例
2017/09/27 Javascript
详解js跨域请求的两种方式,支持post请求
2018/05/05 Javascript
原生实现一个react-redux的代码示例
2018/06/08 Javascript
vue中引入第三方字体文件的方法示例
2018/12/17 Javascript
微信小程序页面滚动到指定位置代码实例
2019/09/07 Javascript
微信小程序获取复选框全选反选选中的值(实例代码)
2019/12/17 Javascript
JavaScript async/await原理及实例解析
2020/12/02 Javascript
[20:21]《一刀刀一天》第十六期:TI国际邀请赛正式打响,总奖金超过550万
2014/05/23 DOTA
[02:15]2014DOTA2国际邀请赛 赛后退役选手回顾
2014/08/01 DOTA
[02:51]2018年度DOTA2最佳中单位选手-完美盛典
2018/12/17 DOTA
Python基于辗转相除法求解最大公约数的方法示例
2018/04/04 Python
python3基于TCP实现CS架构文件传输
2018/07/28 Python
Python基本数据结构之字典类型dict用法分析
2019/06/08 Python
Django实现跨域的2种方法
2019/07/31 Python
解决windows下python3使用multiprocessing.Pool出现的问题
2020/04/08 Python
python利用递归方法实现求集合的幂集
2020/09/07 Python
HTML5安全介绍之内容安全策略(CSP)简介
2012/07/10 HTML / CSS
意大利体育用品网上商城:Nencini Sport
2016/08/18 全球购物
高一学年自我鉴定范文(3篇)
2014/09/26 职场文书
交通事故赔偿协议书怎么写
2014/10/04 职场文书
捐款通知怎么写
2015/04/24 职场文书
幼儿园百日安全活动总结
2015/05/07 职场文书
有关三国演义的读书笔记
2015/06/25 职场文书