1.文本渲染指令

Vue使用了基于HTML的模板语法,允许开发者声明式地将DOM绑定至底层Vue实例的数据。所有Vue的模板都是合法的HTML,所以能被遵循规范的浏览器和HTML解析器解析。

在前面,我们一直使用的是字符串插值的形式渲染文本,但是除此方法之外,vue还提供了其他几种常见的文本渲染方式:

  1. v-text:更新元素的innerText
  2. v-html:更新元素的innerHTML
  1. <body>
  2. <div id="app">
  3. <div v-html="msg"></div>
  4. <div v-text="msg"></div>
  5. </div>
  6. <script src="https://unpkg.com/vue@next"></script>
  7. <script>
  8. Vue.createApp({
  9. data(){
  10. return {
  11. msg:'<p>Hello World!</p>'
  12. }
  13. }
  14. }).mount('#app');
  15. </script>
  16. </body>

在Vue中,我们可以使用{{}}将数据插入到相应的模板中,这种方法是一种文本插值。

使用这种方法,如果网络慢或者JavaScript出错的话,会将{{}}直接渲染到页面中。值得庆幸的是,Vue还提供了v-text和v-html来渲染文本或元素。这样就避免了将{{}}直接渲染到页面中。

2.属性绑定指令

如果想让html标签中的属性,也能应用Vue中的数据,那么就可以使用vue中常用的属性绑定指令:v-bind

<body>
    <div id="app">
        <div v-bind:title="msg">DOM元素属性绑定</div>
        <!-- v-bind的简写形式 -->
        <div :title="msg">DOM元素属性绑定</div>
    </div>

    <script src="https://unpkg.com/vue@next"></script>
    <script>
        Vue.createApp({
            data(){
                return {
                    msg:'Hello World!'
                }
            }
        }).mount('#app');
    </script>
</body>

上面展示的是v-bind的最基本的使用,第一种是完整语法,第二种是缩写方式。

除了将元素的title属性和vue实例的相关字段进行绑定外,还能将其他的属性字段进行绑定,最常见的是对于样式的绑定,即class和style属性。

2.1.绑定样式

使用v-bind指令绑定class属性,就可以动态绑定元素样式了。

p02_01.png

<head>
    <style>
        .one {
            color: red;
        }
        .two {
            color: blue;
        }
    </style>
</head>
<body>
    <div id="app">
        <div :class="className">DOM元素的样式绑定</div>
    </div>

    <script src="https://unpkg.com/vue@next"></script>
    <script>
        Vue.createApp({
            data(){
                return {
                    className: 'one'
                }
            }
        }).mount('#app')
    </script>
</body>

2.2.使用对象语法绑定样式

我们可以给v-bind:class 一个对象,也可以直接绑定数据里的一个对象,以动态地切换class。

p02_02.png

<head>
    <style>
        .one {
            color: red;
        }
        .two {
            font-size: 48px;
        }
    </style>
</head>

<body>
    <div id="app">
        <div :class="{one:oneActive,two:twoActive}">DOM元素的样式绑定</div>
    </div>

    <script src="https://unpkg.com/vue@next"></script>
    <script>
        Vue.createApp({
            el: '#app',
            data() {
                return {
                    oneActive: true,
                    twoActive: true
                }
            }
        }).mount('#app')
    </script>
</body>

2.3.使用三目运算绑定样式

可以使用三目运算符,来动态绑定样式。

<head>
    <style>
        .one {
            color: red;
        }
    </style>
</head>

<body>
    <div id="app">
        <div :class="userId==1?className:''">DOM元素的样式绑定</div>
    </div>

    <script src="https://unpkg.com/vue@next"></script>
    <script>
        Vue.createApp({
            data(){
                return {
                    userId: 1,
                    className: 'one'
                }
            }
        }).mount('#app')
    </script>
</body>

2.4.直接绑定内联样式

也可以直接绑定内联样式。

<body>
    <div id="app">
        <div :style="{color:colorValue,fontSize:fontSizeValue}">DOM元素的样式绑定</div>
    </div>

    <script src="https://unpkg.com/vue@next"></script>
    <script>
        Vue.createApp({
            data(){
                return {
                    colorValue: 'red',
                    fontSizeValue: '48px'
                }
            }
        }).mount('#app')
    </script>
</body>

注意:绑定style属性后,样式的书写要遵循javaScript规范。
也就是将 xxx-xxx 改写成驼峰命名方式 xxxXxxx

3.事件处理指令

3.1.事件绑定

我们可以用 v-on 指令绑定一个事件监听器,通过它调用我们 Vue 实例中定义的方法。

v-on指令可以简写为:@

<body>
    <div id="app">
        <!-- pointme就是点击事件的处理函数 -->
        <button v-on:click="pointme">点击我</button>
        <!-- v-on指令的简写 -->
        <button @click="pointyou">点击你</button>
    </div>

    <script src="https://unpkg.com/vue@next"></script>
    <script>
        Vue.createApp({
            //methods:此处声明Vue方法
            methods: {
                pointme() {
                    alert('点击了我');
                },
                pointyou() {
                    alert('点击了你');
                }
            }
        }).mount('#app');
    </script>
</body>

事件处理时还可以传递参数。比如下面的案例:对一个数进行加减运算

<body>
    <div id="app">
        {{num}}
        <button v-on:click="add(1)">加</button>
        <button @click="subtract(1)">减</button>
    </div>

    <script src="https://unpkg.com/vue@next"></script>
    <script>
        Vue.createApp({
            data() {
                return {
                    num: 1
                }
            },
            methods: {
                add(value) {
                    this.num += value;
                },
                subtract(value) {
                    this.num -= value;
                }
            }
        }).mount('#app');
    </script>
</body>

3.2.事件对象

我们在学习JavaScript时知道,事件处理时会有一个事件对象。事件对象代表事件的状态,比如事件在其中发生的元素、键盘按键的状态、鼠标的位置、鼠标按钮的状态。

在Vue的事件处理中,也可以使用 $event 的形式给事件处理函数传递事件对象。

<div id="app">
    {{num}}
    <button v-on:click="add(1,$event)">加</button>
    <!-- <button v-on:click="add">加</button> -->
</div>

<script src="https://unpkg.com/vue@next"></script>
<script>
    Vue.createApp({
        data() {
            return {
                num: 1
            }
        },
        methods: {
            add(value,event) {
                this.num += value;
                console.log(event);
                console.log(event.target);
            },
        }
    }).mount('#app');
</script>
  • 注意:如果只传递事件对象这一个参数时, 也可以这样简写 v-on:click=”add” , 也就是不加小括号时,默认传递一个事件对象参数。

3.3.事件修饰符

我们还知道,在JavaScript中可以使用 event.preventDefault() 或 event.stopPropagation() 等来阻止事件冒泡,或者阻止浏览器默认行为。那么Vue也提供了这样的功能,叫做事件修饰符。

<style>
    .div1{
        width: 200;
        height: 200;
        background-color: red;
    }
    .div2{
        width: 100;
        height: 100;
        background-color: blue;
    }
</style>

<body>
    <div id="app">
        <div class="div1" @click="divEvent1" @contextmenu.prevent>
            <div class="div2" @click.stop="divEvent2"></div>
        </div>
    </div>

    <script src="https://unpkg.com/vue@next"></script>
    <script>
        Vue.createApp({
            data() {
                return {

                }
            },
            methods: {
                divEvent1() {
                    alert(1)
                },
                divEvent2() {
                    alert(2)
                },
            }
        }).mount('#app');
    </script>
</body>
  • 上面实例中,当点击内层div后,已经不会再触发外层div的点击事件了。也就是使用 stop修饰符阻止了事件冒泡。
  • 当右键单击外层div时不会出现右键菜单,也就是使用prevent修饰符阻止了浏览器默认行为。

4.条件渲染指令

条件渲染指令,可以根据条件判断,来设置元素的显示与隐藏。

4.1.v-if指令

当v-if的值为false时,网页中将不会对此元素进行渲染

p02_03.png

<body>
    <div id="app">
        <div v-if="isShow">DOM元素的样式绑定</div>
    </div>

    <script src="https://unpkg.com/vue@next"></script>
    <script>
        Vue.createApp({
            data() {
                return {
                    isShow: false
                }
            }
        }).mount('#app')
    </script>
</body>

4.2.v-else指令和v-else-if指令

我们可以使用 v-else 指令来表示 v-if 的“else 块”,v-else 元素必须紧跟在 v-if 或者 v-else-if 元素的后面——否则它将不会被识别。而v-else-if则是充当 v-if 的“else-if 块”,可以链式地使用多次。

<body>
    <div id="app">
        <div v-if="type==1">A</div>
        <div v-else-if="type==2">B</div>
        <div v-else-if="type==3">C</div>
        <div v-else>D</div>
    </div>

    <script src="https://unpkg.com/vue@next"></script>
    <script>
        Vue.createApp({
            data(){
                return {
                    type:2
                }
            }
        }).mount('#app');
    </script>
</body>

4.3.v-if指令和v-show指令

v-show也是根据条件展示元素的指令。带有 v-show 的元素始终会被渲染并保留在 DOM 中。
v-show 是简单地切换元素的 CSS 属性 display 。

<body>
    <div id="app">
        <div v-if="isShow">这里是v-if</div>
        <div v-show="isShow">这里是v-show</div>
    </div>

    <script src="https://unpkg.com/vue@next"></script>
    <script>
        Vue.createApp({
            data() {
                return {
                    isShow: false
                }
            }
        }).mount('#app');
    </script>
</body>

p02_04.png

通过上面的例子,我们不难发现两者的不同:

  1. v-if是真正的条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建。
  2. v-if是惰性的,只有当条件为true时才会渲染,如果条件为false则什么都不做
  3. v-if有很高的切换开销,适用于条件不太容易改变的时候
  4. v-show不管条件是true还是false都会进行渲染。并且只是简单地基于 CSS 进行切换
  5. v-show有很高的初始渲染开销,适用于非常频繁地切换

5.循环遍历指令

vue.js 的循环渲染是依赖于 v-for 指令,它能够根据 vue 的实例里面的信息,循环遍历所需数据,然后渲染出相应的内容。它可以遍历数组类型以及对象类型的数据,js 里面的数组本身实质上也是对象,这里遍历数组和对象的时候,方式相似但又稍有不同。

5.1.遍历对象属性

value 是遍历得到的属性值,key 是遍历得到的属性名,index 是遍历次序,这里的 key、index 都是可选参数,如果不需要,这个指令其实可以写成 v-for=”value in user”;

p02_05.png

<body>
    <div id="app">
        <p v-for="(value,key,index) in user">{{index}}:{{key}}:{{value}}</p>
        <hr>
        <p v-for="value in user">{{value}}</p>
    </div>

    <script src="https://unpkg.com/vue@next"></script>
    <script>
        Vue.createApp({
            data() {
                return {
                    user: {
                        userId: 1,
                        userName: '张三',
                        userSex: '男'
                    }
                }
            }
        }).mount('#app');
    </script>
</body>

5.2.遍历数组元素

value 是遍历得到的元素,index 是数组下标,这里的index 也是可选参数,如果不需要,这个指令其实可以写成 v-for=”value in userArr”;

p02_06.png

<body>
    <div id="app">
        <p v-for="(item,index) in userArr">
            {{item.userId}},{{item.userName}},{{item.userSex}}
            <button @click="operate(index)">操作</button>
        </p>
    </div>

    <script src="https://unpkg.com/vue@next"></script>
    <script>
        Vue.createApp({
            data() {
                return {
                    userArr: [{
                        userId: 1,
                        userName: '张三',
                        userSex: '男'
                    }, {
                        userId: 2,
                        userName: '李四',
                        userSex: '女'
                    }, {
                        userId: 3,
                        userName: '王五',
                        userSex: '男'
                    }]
                }

            },
            methods: {
                operate(index) {
                    console.log(this.userArr[index]);
                }
            }
        }).mount('#app');
    </script>
</body>

5.3.关于循环中的key

上面实例中存在一个问题:当更改数组中某一个元素时,Vue会对整个数组进行重新渲染。在实际开发中,这样的代码是不被允许的,在数据量很多的时候,它会严重降低页面的性能。

这时,你可以加唯一性key值,增加后vue就会辨认出哪些内容被渲染后并没有变化,而只渲染新变化的内容。

<!-- 这里使用userId这样一个唯一标识来作为key值 -->
<p v-for="(item,index) in userArr" :key="item.userId">
    {{item.userId}},{{item.userName}},{{item.userSex}}
    <button @click="operate(index)">操作</button>
</p>

6.综合案例

p02_07.png

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title></title>
    <style>
        #app {
            width: 500px;
        }
        table {
            width: 100%;
            border-collapse: collapse;
        }
        table tr th,
        table tr td {
            height: 35px;
            border-bottom: solid 1px #999;
            text-align: center;
        }
        .clear-btn {
            text-align: right;
        }
    </style>
</head>

<body>
    <div id="app">
        <table>
            <tr>
                <th>编号</th>
                <th>姓名</th>
                <th>年龄</th>
                <th>操作</th>
            </tr>
            <tr v-for="(obj,index) in arr">
                <td>{{obj.userId}}</td>
                <td>{{obj.userName}}</td>
                <td>{{obj.userAge}}</td>
                <td><button @click="del(index)">删除</button></td>
            </tr>
            <tr>
                <td colspan="4"><button @click="clear">清空</button></td>
            </tr>
        </table>

        <h3>添加</h3>
        姓名:<input type="text" v-model="userName"><br>
        年龄:<input type="text" v-model="userAge"><br>
        <button @click="add">添加</button>
    </div>

    <script src="https://unpkg.com/vue@next"></script>
    <script>
        Vue.createApp({
            data() {
                return {
                    arr: [
                        {
                            userId: 1,
                            userName: '张三',
                            userAge: 20
                        }, {
                            userId: 2,
                            userName: '李四',
                            userAge: 21
                        }, {
                            userId: 3,
                            userName: '王五',
                            userAge: 22
                        }
                    ],
                    userName: '',
                    userAge: 0
                }
            },
            methods: {
                add() {
                    let userId = 0;
                    if (this.arr.length == 0) {
                        userId = 1;
                    } else {
                        userId = this.arr[this.arr.length - 1].userId + 1;
                    }
                    this.arr.push({
                        userId: userId,
                        userName: this.userName,
                        userAge: this.userAge
                    });
                },
                del(index) {
                    this.arr.splice(index, 1);
                },
                clear() {
                    this.arr.splice(0, this.arr.length);
                    //this.arr = [];
                }
            }
        }).mount('#app')
    </script>
</body>
</html>