Vue.js 的各类指令(Directives)更加方便咱们去数据驱动 DOM,例如 v-bind、v-on、v-model、v-if、v-for、v-once 等内置指令,这些指令的职责就是当表达式改变时将某些行为应用到 DOM 上,尽可能不去操做增删改 DOM。经过了解如何去自定义指令,能够想象内置指令是如何完成的。
在须要特殊功能时,使用自定义指令对 DOM 进行底层操做vue
自定义指令的注册分为全局注册和局部注册,相似组件的注册,只是方法名为 directive
,写法以下:node
// 全局注册 自定义指令 Vue.directive(‘mydir’,{ // 指令选项 }); // 全局注册 自定义指令函数 Vue.directive('mydir', function () { // 这里将会被 `bind` 和 `update` 调用 }) // 局部注册(只针对组件内元素) export default { directives: { mydir: { // 指令选项 } } }
须要注意的是: Vue.directive( ) 注册指令要在实例初始化 new Vue( ) 以前才能全局注册指令。定义指令时驼峰式写法会报错,因此通常小写。
自定义指令的选项是由几个钩子函数(可选)组成,能够根据需求选择不一样的钩子,例如使用全局注册一个指令时:express
Vue.directive('mydir', { bind: function () { // 只调用一次,指令第一次绑定到元素时调用,用于在绑定元素时执行一次的初始化动做。 }, update: function () { // 第一次是紧跟在 bind 以后调用,得到的参数是绑定的初始值, // 以后被绑定元素所在的模板更新时调用,而不论绑定值是否变化,能够忽略没必要要的模板更新。 }, inserted: function () { // 被绑定元素插入父节点时调用(父节点存在便可调用,没必要存在于 document 中)。 }, componentUpdated: function () { // 被绑定元素所在模板完成一次更新周期时调用。 }, unbind: function () { // 只调用一次, 指令与元素解绑时调用。 } })
以上每一个钩子函数都有几个参数可用:数组
// 一个带自定义指令的元素 <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) } } } }
控制台输出截图:svg
其中对于 binding
对象输出的属性有:函数
Vue 内置指令 v-bind
用于动态更新 HTML 元素属性,使用 v-bind:someAttr = "someData"
或者语法糖 :someAttr = "someData"
就能够在 someData 改变时更新绑定的 someAttr 属性。测试
绑定单一的属性值this
<a :href="url" :id="linkID">连接</a>
测试 data 以下:url
// js data : { url: 'https://www.baidu.com/', linkID : 'myid' }
元素渲染输出:
<a href="https://www.baidu.com/" id="myid">连接</a>spa
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:someEvent = "someFunction"
或者语法糖 @someEvent = "someFunction"
就能够监听 someEvent 进行交互。
@someEvent
调用的方法名后面能够不跟(),例如:
<a :href="url" :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/" 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
根据表达式的值的真假条件渲染元素,在表达式为真时渲染,为假时移除。
<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
经常使用于数组遍历或枚举一个对象的循环显示,必须结合 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-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> 和组件。
.lazy
- 取代 input 监听 change 事件.number
- 输入字符串转为数字.trim
- 输入首尾空格过滤这三个指令的共同点是无需表达式,用法以下:
<!-- 不显示未编译的标签直到实例初始化完 --> <div v-cloak>{{ message }}</div> <!-- 须要配合 CSS 隐藏样式 [v-cloak]{ display: none;}--> <!-- 只渲染一次,随后的渲染将被视为静态内容并跳过 --> <div v-once>{{ message }}</div> <!-- 不会被编译,直接显示显示原始{{ }}标签 --> <div v-pre>{{ message }}</div>