【Vue.js 2.0】指令


一、内置指令

1. v-bind 主要用于动态绑定DOM元素属性(attribute),即元素属性实际的值是由vm实例中的data属性提供的。例如:

<img v-bind:src='imgPath' />
<script>
    var app = new Vue({
        data:{
            imgPath: 'http://...'
        }
    })
script>

2. v-model 主要对表单元素进行双向数据绑定,在修改表单元素值的同时,实例vm中对应的属性值也同时更新,反之亦然。输入框示例:

<div id="app">
    <h1>输入内容为:{{message}}h1>
    <input type="text" v-model="message" />
div>

<script>
    var app = new Vue({
        el: '#app',
        data: {
            message: 'this is v-model example'
        }
    })
script>

Vue.js 2.0中取消了lazy和number作为参数,用修饰符(modifier)来代替:

<input type="text" v-model.lazy="message" />  <%-- 加lazy后会更改为在change事件中同步 --%>
<input type="text" v-model.trim="message" /> <%-- 去掉输入值的首尾空格 --%>
<input type="number" v-model.number="message" /> <%-- 自动将用户的输入值转为数值类型。即使input输入框的type=number类型,获取到的值也是string类型,如果加上.number获取到的值则为number类型 --%>

3. v-if  v-else  v-show 主要用于根据条件展示对应的模板内容。需要注意的是,v-else必须紧跟v-if,不然该指令不起作用,例如:

<div id="app">
    <div v-if="yes">yesdiv>
    <p>the v-else div showsp>
    <div v-else>nodiv>
div>

<script>
    var app = new Vue({
        el: '#app',
        data: {
            yes: false
        }
    })
//显示:the v-else div shows
script>

除了 v-if,v-show 也是可以根据条件展示元素的一种指令。与v-if 不同的是,v-show 元素的使用会渲染并保持在 DOM 中。v-show 只是切换元素的 css 属性 display。v-if 的切换消耗要比 v-show 高,但初始条件为 false 的情况下,v-if 的初始渲染要稍快。

4. v-for 主要用于列表渲染,将根据接收到的数组重复渲染v-for绑定到的DOM元素及内部的子元素,并且可以通过设置别名的方式,获取数组内的数据并渲染到节点中。例如:

<div id="app">
    <p>--------------------列表渲染--------------------p>
    <ul>
        <%-- items为data中的属性名,item为别名,可以通过item来获取当前数组遍历的每个元素--%>
        <li v-for="item in items">
            <h3>{{item.title}}h3>
            <p>{{item.description}}p>
        li>
    ul>
    <p>--------------------列表渲染 + 索引--------------------p>
    <ul>
        <%-- 也可以用 of 替代 in 作为分隔符,因为它更接近 JavaScript 迭代器的语法;index为当前数组元素的索引--%>
        <li v-for="(item, index) of items">
            <h3>{{index}}:{{item.title}}h3>
            <p>{{item.description}}p>
        li>
    ul>
    <p>--------------------列表渲染 + (key, value)形式--------------------p>
    <ul>
        <li v-for="(value, key) of objectDemo">
            <h3>{{key}}h3>
            <p>{{key}}:{{value}}p>
        li>
    ul>
    <p>--------------------列表渲染 + template--------------------p>
    <ul>
        <template v-for="item in items">
        <li>{{ item.title }}li>
        <li>{{item.description}}li>
      template>
    ul>
    <p>--------------------迭代1-10--------------------p>
    <ul>
        <%--Vue.js 2.0之后n 由原来的 09 迭代变成 110 迭代--%>
        <li v-for="n in 10">{{ n }}
        li>
    ul>
    <p>--------------------v-bind:key--------------------p>
   <%-- key的作用就是为了防止更新了数据的时候重新渲染整个列表,有key相当于做了一个缓存,只会去重新渲染更新了的数据--%>
    <div v-for="item in items" v-bind:key="item.id">
         <h3>{{item.title}}h3>
    div>
div>

<script>
    var app = new Vue({
        el: '#app',
        data: {
            yes: true,
            items: [
                { title: 'title-1', description: 'description-1' },
            { title: 'title-2', description: 'description-2' },
            { title: 'title-3', description: 'description-3' },
            { title: 'title-4', description: 'description-4' }
            ],
            objectDemo: {
                a: 'a-value',
                b: 'b-value',
                c: 'c-value'
            }
        }
    })
script>

5. v-on 主要用于事件绑定

<div id="app">
    <%-- 按钮1、按钮2等价,响应结果:弹框输出 Hello Vue.js --%>
    <button v-on:click="say">按钮1button>
    <button @click="say">按钮2button>


    <%-- v-on 也支持内联 JavaScript 语句,但仅限一个语句,响应结果:弹框输出 Hello Vue.js from param --%>
    <button v-on:click="sayFrom ('from param')">按钮3button>

    <%-- 同一元素上也可以通过 v-on 绑定多个相同事件函数,执行顺序为顺序执行,响应结果:依次弹框输出 Hello Vue.js:one;Hello Vue.js:two --%>
    <button v-on:click="sayFrom (':one'), sayFrom (':two')">按钮4button> 
div>

<script>
    var app = new Vue({
        el: '#app',
        data: {
            msg: 'Hello Vue.js'
        },
        methods: {
            say: function () {
                alert(this.msg);
            },
            sayFrom: function (from) {
                alert(this.msg + '' + from);
            }
        }
    })
script>  
5.1 .prevent 调用 event.preventDefault();.self只当事件是从侦听器绑定的元素本身触发时才触发回调;v-on:click.self.prevent 和 v-on:click.prevent.self的区别:
<%-- 节点关系:div标签>a标签>P标签 --%>
<div style="border: 1px solid #000; padding: 10px; margin: 10px">
    <div v-on:click="alert('爷爷')">
        <a href="https://www.baidu.com" v-on:click="alert('爸爸')">爸爸
          <p v-on:click="alert('儿子')">儿子p>
        a>
    div>
    <%--结果说明:点击'爷爷'会弹出'爷爷'不跳转;点击'爸爸'会依次弹出'爸爸'、'爷爷'并跳转;点击'儿子'会依次弹出'儿子'、'爸爸'、'爷爷'并跳转。这发生了事件冒泡--%>

    <%--v-on:click.self.prevent 阻止对元素自身的点击,.prevent修饰符在后,修饰的是元素的v-on事件在被.self修饰后的事件,所以它只能阻止对元素自身的点击,无法阻止事件冒泡--%>
    <div v-on:click="alert('爷爷')">
        <a href="https://www.baidu.com" v-on:click.self.prevent="alert('爸爸')">爸爸
          <p v-on:click="alert('儿子')">儿子p>
        a>
    div>
    <%--结果说明:点击'爷爷'会弹出'爷爷'不跳转;点击'爸爸'会依次弹出'爸爸'、'爷爷'不跳转;点击'儿子'会依次弹出'儿子'、'爷爷'并跳转。分析:点击自身,.prevent修饰符阻止了标签的默认事件,但是事件冒泡没有阻止;.self修饰符阻止了事件冒泡时触发元素本身绑定的事件 --%>

    <%--v-on:click.prevent.self 阻止所有的点击,.prevent修饰符在前,修饰的是元素的v-on事件,所以它会阻止所有的点击,自身点击和事件冒泡--%>
    <div v-on:click="alert('爷爷')">
        <a href="https://www.baidu.com" v-on:click.prevent.self="alert('爸爸')">爸爸
          <p v-on:click="alert('儿子')">儿子p>
        a>
    div>
    <%--结果说明:点击'爷爷'会弹出'爷爷'不跳转;点击'爸爸'会依次弹出'爸爸'、'爷爷'不跳转;点击'儿子'会依次弹出'儿子'、'爷爷'不跳转。分析:不管是点击自身还是由于事件冒泡,.prevent修饰符都阻止了标签的默认事件;.self修饰符阻止了事件冒泡时触发元素本身绑定的事件 --%>
div>
5.2 v-on:click.stop 调用 event.stopPropagation()
<div id="app">
    <div v-on:click="dodo">
        <%-- 先弹出'noclick',再弹出'dodo' --%>
        <button v-on:click="doThis">单击事件button>
        <%--只弹出'noclick'--%>
        <button v-on:click.stop="doThis">阻止单击事件继续传播button>
    div>
div>

<script>
    var app = new Vue({
        el: '#app',
        data: {
            msg: 'Hello Vue.js'
        },
        methods: {
            doThis: function () {
                alert("noclick");
            },
            dodo: function () {
                alert("dodo");
            }
        }
    })
script>

6. v-text和v-html

<div id="app"> 
    <p v-html="html">p> 
    <p v-text="text">p> 
div>

<script>
    var app = new Vue({
        el: '#app',
        data: { 
            html: "

html标签在渲染的时候被解析

", text: "

html标签在渲染的时候被源码输出

", }, beforeDestroy: function () { debugger } }) script>

8. v-once 用于标明元素或组件只渲染一次,即使随 后发生绑定数据的变化或更新,该元素或组件及包含的子元素都不会再次被编译和渲染

<div id="app">
    <p>{{message}}p> 
    <p v-once>{{msg}}p>  
div>

<script>
    var app = new Vue({
        el: '#app',
        data: {
            message: 'aaa',
            msg: 'bbb',
        }, 
    })
script>

二、自定义指令

1. 注册指令

Vue.directive(id, definition)

2. 指令的定义对象

 1 
 2     
"app"> 3
"color">{{num}}
4

5 6

7
8

9 10

11 12 47

指令的钩子函数(都是可选函数)

  1. bind: 只被调用一次,在指令第一次绑定到元素上时调用
  2. inserted:被绑定元素插入父节点时调用(仅保证父节点存在,但不一定已被插入文档中)
  3. update :指令绑定 bind 函数执行后不直接调用 update 函数, 只要组件发生重绘,无论指令接受的值是否发生变化,均会调用 update 函数,update 接收到的参数为 newValue 和 oldValue。如果需要过滤不必要的更新,则可以使用 binding.value == binding.oldValue 来判断
  4. componentUpdate:当整个组件都完成了 update 状态后即所有 DOM 都更新后调用该钩子函数,无论指令接受的参数是否发生变化
  5. unbind :指令从元素上解绑时调用,只调用一次

3. 对象字面量

如果指令需要多个值,可以传入一个JavaScript对象字面量,指令函数能够接受所有合法的JavaScript表达式

 1 
 2     
"app"> 3
"{color:'white',text:'hello!'}">
4
5 6 15

4. 指令实例属性

 1 
 2     
"app"> 3
"message">
4
5 6 26

  1. el:指定所绑定的元素,可以直接操作DOM
  2. binding:一个对象,包含若干属性
  3. vnode:Vue编译生成的虚拟节点
  4. oldVnode:上一个虚拟节点,尽在update和componentUpdated钩子函数中可用

binding对象包含的属性:

  • name:指令名,不包含v-前缀
  • value:指令的绑定值,例如:v-mode='1+1'中,绑定值为2
  • oldValue:指定绑定的前一个值,仅在update和componentUpdate钩子中可用,无论是否改变都可用
  • expression:字符串形式的指令表达式,例如:v-mode='1+1'中,表达式为'1+1'
  • arg:传给指令的参数、可选。例如v-demo:foo中,参数为'foo'
  • modifiers:一个包含修饰符的对象。例如:v-demo.foo.bar中,修饰符对象为{foo:true,bar:true}