2. 基础语法

2.1. 插值操作

通过插值操作可以完成vue对象的数据,填充到html中去。

<h2> {{ message }} </h2>

2.1.1. v-once

可以完成vue仅仅一次的数据绑定,后续的数据修改不在同步页面。

2.1.2. v-html

可以将数据中的html内容,以html展示到页面上。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<!doctype html>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
<div id="app">
    <p>Using mustaches: {{ rawHtml }}</p>
    <p>Using v-html directive: <span v-html="rawHtml"></span></p>

</div>
<script src="../js/vue.js"></script>
<script>
    let app = new Vue({
        el: "#app",
        data: {
            rawHtml: '<span style="color:red"> this should be red</span>'
        }
    })
</script>
</body>
</html>

2.1.3. v-text

可以将数据中的html内容,以text展示到页面上。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<!doctype html>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
<div id="app">
    <p>Using mustaches: {{ rawHtml }}</p>
    <p>Using v-text directive: <span v-text="rawHtml"></span></p>

</div>
<script src="../js/vue.js"></script>
<script>
    let app = new Vue({
        el: "#app",
        data: {
            rawHtml: '<span style="color:red"> this should be red</span>'
        }
    })
</script>
</body>
</html>

2.1.4. v-pre

用于跳过这个元素和他子元素的编译过程,用于展示原本内容。

2.1.5. v-cloak

某些情况下 ,浏览器可能会直接展示未编译的mustache标签。 通过此可以不展示这些信息。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<!doctype html>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">

    <title>Document</title>
    <style>
        [v-cloak] {
            display: none   ;
        }
    </style>
</head>
<body>

<div id="app" v-cloak>
    <h2  >{{ cnt }}</h2>

</div>
<script src="../js/vue.js"></script>
<script>
    setTimeout(function(){
    let app = new Vue({
        el: "#app",
        data: {
            cnt: 1,
        }
    })},3000)
</script>
</body>
</html>

2.2. 绑定属性

v-bind可以绑定属性。

2.2.1. 绑定基本使用

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
<!DOCTYPE html>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">
    <img :src="srcUrl" alt="">

</div>
<script src="../js/vue.js"></script>
<script>
    let app = new Vue({
        el: "#app",
        data: {
            srcUrl: "https://i1.hdslb.com/bfs/face/c850c18ae6b507d0ef34837f53a51090b6a7451f.jpg@96w_96h_1c.webp"
        }
    })
</script>
</body>
</html>

2.2.2. 动态绑定class

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<!doctype html>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        .active{
            color:  red;
        }
        .line{
            background-color: blue;
        }
    </style>
</head>
<body>
<div id="app">
    <h2 v-bind:class="getClass()">{{message}}</h2>

</div>
<script src="../js/vue.js"></script>
<script>
    let app = new Vue({
        el: "#app",
        data: {
            message: "panda",
            isActive: true,
            isLine: true
        },
        methods:{
            getClass: function(){
                return {active:this.isActive,line:this.isLine}
            }
        }
    })
</script>
</body>
</html>

2.2.3. 动态绑定style

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<!doctype html>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        .active{
            color:  red;
        }
        .line{
            background-color: blue;
        }
    </style>
</head>
<body>
<div id="app">
    <h2 v-bind:style="{fontSize: messageFontSize}">{{message}}</h2>

</div>
<script src="../js/vue.js"></script>
<script>
    let app = new Vue({
        el: "#app",
        data: {
            message: "panda",
            messageFontSize: "100px",
        },
        methods:{

        }
    })
</script>
</body>
</html>

2.2.4. v-for和v-bind作业

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<!doctype html>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        .active{
            color:  red;
        }
        .line{
            background-color: blue;
        }
    </style>
</head>
<body>
<div id="app">
    <ul>
        <li v-for="(zoom,index) in zooms">
            <p v-bind:class="{active: curentIndex==index}" @click="ChangeClass($event,index)"> {{index }} - {{ zoom }} </p>
        </li>
    </ul>
</div>
<script src="../js/vue.js"></script>
<script>
    let app = new Vue({
        el: "#app",
        data: {
            zooms: ['cat','dog','pig'],
            curentIndex:0,
            isActive: false
        },
        methods:{
            ChangeClass: function (event,index){
                this.curentIndex =index
            }
        }
    })
</script>
</body>
</html>

2.3. 计算属性

可以根据已有的属性生成其他属性。

2.3.1. 基本使用

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<!DOCTYPE html>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">
    <h2>{{ fullName }}</h2>

</div>
<script src="../js/vue.js"></script>
<script>
    let app = new Vue({
        el: "#app",
        data: {
            firstName: "jie di",
            secondName: "zhao",
        },
        computed:{
            fullName: function (){
                return this.secondName + " " + this.firstName
            }
        }
    })
</script>
</body>
</html>

2.3.2. 复杂使用

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<!DOCTYPE html>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">
    <h2>{{ totalPrice }}</h2>

</div>
<script src="../js/vue.js"></script>
<script>
    let app = new Vue({
        el: "#app",
        data: {
            books: [
                {id:1,name:'abc',price:100},
                {id:2,name:'abc',price:101},
                {id:3,name:'abc',price:102},
                {id:4,name:'abc',price:103},
            ]
        },
        computed:{
            totalPrice: function (){
                let result=0
                // for (let i=0; i< this.books.length; i++){
                //     result +=this.books[i].price
                // }
                for (let book of this.books){
                    result += book.price
                }
                return result
            }
        }
    })
</script>
</body>
</html>

2.3.3. getter和setter

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<!doctype html>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
<div id="app">
    <h2>{{ fullName }}</h2>

</div>
<script src="../js/vue.js"></script>
<script>
    let app = new Vue({
        el: "#app",
        data: {
            firstName: "jiedi",
            secondName: "zhao",
        },
        computed:{
            // fullName: function(){
            //     return this.firstName+ this.secondName
            // },

            fullName: {
                get: function (){
                    return this.firstName + " " + this.secondName
                },
                set: function (newValue){
                    const names = newValue.split(" ")
                    this.firstName = names[0]
                    this.secondName =names[1]
                }
            }

        }
    })
</script>
</body>
</html>
../_images/getterandsetter.png

2.3.4. 计算属性和methods的对比

计算属性是缓存的, 方法是不缓存的。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
<!DOCTYPE html>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">
    <h2>{{ fullName }}</h2>
    <h2>{{ fullName }}</h2>
    <h2>{{ fullName }}</h2>
    <h2>{{ fullName }}</h2>
    <h2>{{ getFullName() }}</h2>
    <h2>{{ getFullName() }}</h2>
    <h2>{{ getFullName() }}</h2>
    <h2>{{ getFullName() }}</h2>

</div>
<script src="../js/vue.js"></script>
<script>
    let app = new Vue({
            el: "#app",
            data: {
                firstName: "jie di",
                secondName: "zhao",
            },
            methods:{
                getFullName: function(){
                    console.log("------getFullName------")
                    return this.secondName + " " + this.firstName
                },
            },
            computed: {
                fullName: function () {
                    console.log("------fullName------")
                    return this.secondName + " " + this.firstName
                }
            }
        })
        </script>
</body>
</html>
../_images/计算属性和方法的对比.png

2.4. 事件监听

事件监听用于在用户点击、拖拽等场景。

2.4.1. 监听基本使用

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<!doctype html>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
<script src="../js/vue.js"></script>

<div id="app">
    <h2>{{ cnt }}</h2>
    <button @click="add">+</button>
    <button @click="sub">-</button>

</div>
<script>
    let app = new Vue({
        el: "#app",
        data: {
            cnt:1,
        },
        methods:{
            add: function (){
                this.cnt+=1
                console.log("-----add-------" )
            },
            sub: function(){
                this.cnt-=1
                console.log("-----sub-------" )
            }
        }

    })
</script>

</body>
</html>

2.4.2. 参数传递

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<!DOCTYPE html>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">
    <button @click="bntClick">按钮1</button>
    <button @click="bntClick2(12,$event)">按钮2</button>

</div>
<script src="../js/vue.js"></script>
<script>
    let app = new Vue({
        el: "#app",
        data: {
            cnt: 1,
        },
        methods:{
            bntClick(event){
                console.log(event)
            },
            bntClick2(abc,event){
                console.log("第一个参数:" + abc)
                console.log("第二个参数:" + event)
            },
        }
    })
</script>
</body>
</html>
../_images/事件参数.png

2.4.3. 修饰符

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
<!DOCTYPE html>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">
    <div @click="divClick">
        <button @click.stop="btnClick">button1</button>
    </div>
<!--    <div @click="divClick">-->
<!--        <button @click="btnClick">button1</button>-->
<!--    </div>-->

    <form action="baidu">
        <input type="submit" value="提交" @click.prevent="submitClick">
    </form>

        <input type="text" value="提交2" @keyup.enter="keyup">

</div>
<script src="../js/vue.js"></script>
<script>
    let app = new Vue({
        el: "#app",
        data: {

        },
        methods:{
            btnClick(){
                console.log("btn click")
            },
            divClick(){
                console.log("div click")
            },
            submitClick(){
                console.log("div click")
            },
            keyup(){
                console.log("key up")
            }
        }
    })
</script>
</body>
</html>
../_images/事件冒泡.png

2.5. 条件判断

2.5.1. v-if

简单的判定

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<!DOCTYPE html>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">
<!--    <h2 v-if="isShow">{{ cnt }}</h2>-->


    <h2 v-if="isShow">
        <div>abc</div>
        <div>abc</div>
        <div>abc</div>
        {{ message }}
    </h2>

</div>
<script src="../js/vue.js"></script>
<script>
    let app = new Vue({
        el: "#app",
        data: {
            isShow: true,
            message: "abc",
        }
    })
</script>
</body>
</html>

2.5.2. v-else-if

稍微复杂的判定

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
<!DOCTYPE html>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">
    <h2 v-if="score>90">优秀 </h2>
    <h2 v-else-if="score>80">良好</h2>
    <h2 v-else-if="score>60">及格 </h2>
    <h2 v-else> 不及格</h2>
    <br>
    <br>
    <br>
    <h2 > {{result}} </h2>
</div>
<script src="../js/vue.js"></script>
<script>
    let app = new Vue({
        el: "#app",
        data: {
            score: 80
        },
        computed:{
            result(){
              let message=''
              if (this.score >90){
                  message ="优秀"
              }
              else if (this.score >80){
                  message="良好"
              }
              else if (this.score >60){
                  message="及格"
              }
              else  {
                  message = "不及格"
              }
              return message
            },
        }
    })
</script>
</body>
</html>

2.5.3. 用户登录案例

进行一个用户登录切换的案例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<!DOCTYPE html>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">
   <span v-if="currentType == 'username'">用户名</span>
    <span v-if="currentType == 'email'">用户邮箱</span>
    <input type="text"> </input>
    <button @click="btnClick"> 切登录方式</button>
</div>
<script src="../js/vue.js"></script>
<script>
    let app = new Vue({
        el: "#app",
        data: {
           currentType: "username",
        },
        methods:{
            btnClick(){
                if (this.currentType == "username" ){
                    this.currentType="email"
                }
                else if (this.currentType == "email" ){
                    this.currentType="username"
                }
            }
        }
    })
</script>
</body>
</html>

2.5.4. v-show

当需要在显示和隐藏之间切回频繁的时候使用 v-show。只有一次切回使用v-if 。

2.6. 循环

2.6.1. v-for遍历数组

简单遍历数组样例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<!DOCTYPE html>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">
    <ul>
        <li v-for="(name,index) in names ">{{index }} {{ name}}</li>
    </ul>

    <ul>
        <li v-for="(v,k,index) in person ">{{index }} {{ k}} {{ v}}</li>
    </ul>
</div>
<script src="../js/vue.js"></script>
<script>
    let app = new Vue({
        el: "#app",
        data: {
           names: [ "panda","pdna02", "panda03"],
            person:{
               name: 'zhaojiedi',
                age: 28,
                weight: 60,
            }
        }
    })
</script>
</body>
</html>

2.6.2. v-for遍历对象

简单遍历数组样例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<!DOCTYPE html>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">
    <ul>
        <li v-for="(v,k,index) in person ">{{index }} {{ k}} {{ v}}</li>
    </ul>
</div>
<script src="../js/vue.js"></script>
<script>
    let app = new Vue({
        el: "#app",
        data: {
            person:{
               name: 'zhaojiedi',
                age: 28,
                weight: 60,
            }
        }
    })
</script>
</body>
</html>

2.6.3. v-for遍历添加key

添加key避免插入对象导致大量的对象移动。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<!DOCTYPE html>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">
    <ul>
        <li v-for="(name,index) in names " :key="name">{{index }} {{ name}}</li>
    </ul>

    <button @click="btnClick">添加</button>

</div>
<script src="../js/vue.js"></script>
<script>
    let app = new Vue({
        el: "#app",
        data: {
            names: [ "panda","pdna02", "panda03"],
            person:{
                name: 'zhaojiedi',
                age: 28,
                weight: 60,
            }
        },
        methods:{
            btnClick(){
                this.names.push("panda05")
            },
        }
    })
</script>
</body>
</html>

2.6.4. v-for数组哪些是响应式的

目前一些数组操作是支持响应式的, 不是所有修改都是响应式的。 通过索引方式修改对象是无法响应式的。可以通过splice来实现。 或者使用vue.set方式。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
<!DOCTYPE html>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">
    <ul>
        <li v-for="(name,index) in names " :key="name">{{index }} {{ name}}</li>
    </ul>

    <button @click="btnClick">添加</button>

</div>
<script src="../js/vue.js"></script>
<script>
    let app = new Vue({
        el: "#app",
        data: {
            names: [ "panda","pdna02", "panda03"],
            person:{
                name: 'zhaojiedi',
                age: 28,
                weight: 60,
            }
        },
        methods:{
            btnClick(){
                //push
                // pop
                // unshift
                // splice
                // sort
                // reverse

                this.names.push("panda05")

                // 这是非响应式的。
                this.names[0]="zhaojiedi"
                // 这是响应式的
                this.names.splice(1,1,"zhaojiedi")
                //这是是响应式的
                Vue.set(this.names,0,'zhaojiedi')
            },
        }
    })
</script>
</body>
</html>

2.7. 购入车案例

2.7.1. 案例考察点分析

本基础案例考察了如下几点

  • html

  • css

  • v-if,v-else

  • filters

  • methods click

  • computed

  • v-for

2.7.2. 详细代码

下面展示各个代码的详细内容。

2.7.2.1. html

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
<!DOCTYPE html>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="style.css">

</head>
<body>


<div id="app">

    <div v-if="infos.length>=1">
<table>
    <th>
        <td>书籍名称</td>
        <td>出版日期</td>
        <td>价格</td>
        <td>购买数量</td>
        <td>操作</td>
    </th>
    <tr v-for="(item,index) in infos" >
        <td>{{index}}</td>
        <td>{{item.name}}</td>
        <td>{{item.date}}</td>
        <td>{{item.price|formatPrice}}</td>
        <td>
            <button @click="sub(item)" :disabled="item.count<=1">-</button>
            {{item.count}}
            <button @click="add(item)">+</button>
        </td>
        <td><button @click="removeLine(index)">移除</button></td>
    </tr>
</table>
   总价: {{totalPrice|formatPrice}}
    </div>
    <h2 v-else>没有商品的</h2>
</div>

<script src="../js/vue.js"></script>
<script src="./main.js"></script>
</body>
</html>

2.7.2.2. style

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
table{
    border-spacing: 0;
}
th,td{
    padding: 8px 16px;
    border: 1px solid #e9e9e9;
    text-align: left;
}
th{
    background-color: #f7f7f7;
    color: #5c6b77;
    font-weight: 600;
}

2.7.2.3. js

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
let app = new Vue({
        infos: [
            {"name": "算法导论", "date": "2006-9", "count": 1, "price": 85},
            {"name": "编程艺术", "date": "2006-2", "count": 1, "price": 59},
            {"name": "编程珠玑", "date": "2008-10", "count": 1, "price": 39},
            {"name": "代码大全", "date": "2006-3", "count": 1, "price": 128},
        ],

    },
    methods: {
        add(item) {
            console.log("add")
           item.count++
        },
        sub(item) {
           item.count--
        },
        removeLine(index) {
            this.infos.splice(index, 1)
        }
    },
    filters: {
        formatPrice(price) {
            return "¥ " + price.toFixed(2)
        }
    },
    computed: {
        totalPrice() {
            let totalPriceSum = 0
            for (let info of this.infos) {
                totalPriceSum += info.count * info.price
            }
            return totalPriceSum
        }
    }
})