【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">yes</div>
    <p>the v-else div shows</p>
    <div v-else>no</div>
</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>
View Code

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

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


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

    <%-- 同一元素上也可以通过 v-on 绑定多个相同事件函数,执行顺序为顺序执行,响应结果:依次弹框输出 Hello Vue.js:one;Hello Vue.js:two --%>
    <button v-on:click="sayFrom (':one'), sayFrom (':two')">按钮4</button> 
</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>  
View Code
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修饰符阻止了<a>标签的默认事件,但是事件冒泡没有阻止;.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修饰符都阻止了<a>标签的默认事件;.self修饰符阻止了事件冒泡时触发元素本身绑定的事件 --%>
</div>
View Code
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>
View Code

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: "<h1>html标签在渲染的时候被解析</h1>",
            text: "<h1>html标签在渲染的时候被源码输出</h1>",
        },
        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 <body>
 2     <div id="app">
 3         <div v-lang="color">{{num}}</div>
 4         <p>
 5             <button v-on:click="add">add</button>
 6         </p>
 7     </div>
 8     <p>
 9         <button onclick='unbind()'>解绑</button>
10     </p>
11 
12     <script type="text/javascript">
13         function unbind() {
14             console.log('6 - unbind');//另外起一个方法解绑
15         }
16 
17         Vue.directive('lang', { //五个注册指令的钩子函数
18             bind: function () { //被绑定
19                 console.log('1 - bind');
20             },
21             inserted: function () { //绑定到节点
22                 console.log('2 - inserted');
23             },
24             update: function () { //组件更新
25                 console.log('3 - update');
26             },
27             componentUpdated: function () { //组件更新完成
28                 console.log('4 - componentUpdated');
29             },
30             unbind: function () { //解绑
31                 console.log('5 - unbind');
32             }
33         })
34         var vm = new Vue({
35             el: "#app",
36             data: {
37                 num: 10,
38                 color: 'red'
39             },
40             methods: {
41                 add: function () {
42                     this.num++;
43                 }
44             }
45         })
46     </script>
47 </body>
View Code

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

  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 <body>
 2     <div id="app">
 3         <div v-demo="{color:'white',text:'hello!'}"></div>
 4     </div>
 5 
 6     <script type="text/javascript">
 7         Vue.directive('demo', function (el, binding) {
 8             console.log(binding.value.color);    // 输出'white'
 9             console.log(binding.value.text);    // 输出'hello!'
10         });
11         new Vue({
12             el: '#app',
13         });
14     </script>
15 </body>

4. 指令实例属性

 1 <body>
 2     <div id="app">
 3         <div v-demo="message"></div>
 4     </div>
 5 
 6     <script type="text/javascript">
 7         Vue.directive('demo', {
 8             bind: function (el, binding, vnode) {
 9                 let s = JSON.stringify;
10                 el.innerHTML =
11                 'name:' + s(binding.name) + '<br>' +
12                 'value:' + s(binding.value) + '<br>' +
13                 'expression:' + s(binding.expression) + '<br>' +
14                 'argument:' + s(binding.arg) + '<br>' +
15                 'modifiers:' + s(binding.modifiers) + '<br>' +
16                 'vnode keys:' + Object.keys(vnode).join(',')
17             }
18         });
19         new Vue({
20             el: '#app',
21             data: {
22                 message: 'hello'
23             }
24         });
25     </script>
26 </body>
View Code

  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}

 

posted @ 2021-06-04 17:46  智者见智  阅读(78)  评论(0编辑  收藏  举报