首页 Vue基础
文章
取消

Vue基础

vue框架的特点

  • 相比JavaScript,vue作为前端框架更加强大
  • 简化dom操作,vue通过特殊的语法操作dom元素
  • 响应式数据驱动,页面由数据组成,数据一旦发生改变,页面随之改变

el挂载点

1.el设置的是Vue实例挂载(管理)的元素,经挂载的元素,包括其后代元素都会被Vue实例管理

2.推荐在el中使用id选择器挂载元素,虽然可以选择其他元素

3.推荐挂载双标签元素,但不建议挂载html和body元素

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>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>
<body>
    <!-- el挂载的元素内部,可以使用声明的数据,外部不行 -->
    
    <div id="app">
        
        <br>
        <span>
            
        </span>
    </div>

    <script>
        var app = new Vue({
            el:"#app",
            data:{
                msg:"hello vue!"
            }
        })
    </script>

</body>
</html>

data数据对象

Vue实例使用的数据都会定义在data数据对象中

javascript常见数据类型

值类型:数字(Number),字符串(String),布尔(Boolean),null,undefined;与Java不同的是JavaScript字符串是数值型,而不是引用型

引用数据类型(对象类型):对象(Object),数组(Array),函数(Function)

1
2
3
4
5
6
7
8
9
var x;               // x 为 undefined
var x = 5;           // 现在 x 为数字
var x = "John";      // 现在 x 为字符串

typeof "John"                // 返回 string
typeof 3.14                  // 返回 number
typeof false                 // 返回 boolean
typeof [1,2,3,4]             // 返回 object
typeof {name:'John', age:34} // 返回 object

undefined和null

undefined用于变量,属性和方法,null用于对象

数组

如何判断类型是数组

用typeof判断数组类型依然是object,实际判断数组类型可以使用isArray方法和instanceof操作符

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 1.使用isArray方法
var cars=new Array();
cars[0]="Saab";
cars[1]="Volvo";
cars[2]="BMW";

// 判断是否支持该方法
if (Array.isArray) {
    if(Array.isArray(cars)) {
        document.write("该对象是一个数组。") ;
    }
}

if (cars instanceof Array) {
    document.write("该对象是一个数组。") ;
}
创建数组的方法
1
2
3
4
5
6
7
8
9
10
// 第一种方法
var arr = new Array();
arr[0] = "saab";
arr[1] = "saas";

// 第二种方法
var arr = new Array("saab","saas");

// 第三种方法
var arr = ["saab","saas"];

data数据对象使用示例

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
49
50
51
52
53
54
55
56
57
58
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>

<body>
    <!-- el挂载的元素内部,可以使用声明的数据,外部不行 -->
    <h1>我的云盘</h1>
    <table id="app">
        <tr>
            <th>称号</th>
            <th>\{\{my_net_disk_name\}\}</th>
        </tr>
        <tr>
            <td>名称</td>
            <td>\{\{driver_config.name\}\}"</td>
        </tr>
        <tr>
            <td>存储源类型</td>
            <td>\{\{driver_config.type\}\}</td>
        </tr>
        <tr>
            <td>存储源根地址</td>
            <td>\{\{driver_config.root_url\}\}"</td>
            <!-- 出问题的地方 -->
            <!-- <td><a href=""></td> -->
        </tr>
        <tr>
            <td>文件</td>
            <td>\{\{driver_config.files[0]\}\}</td>
        </tr>

        
    </table>

    <script>
        var app = new Vue({
            el: "#app",
            data: {
                my_net_disk_name: "my_net_disk",
                driver_config: {
                    id: 1,
                    name: "蓝色空间号",
                    type: "阿里云存储",
                    root_url: "www.flameking.com",
                    files: ["葵花宝典", "降龙十八掌", "如来神掌", "狮吼功"]
                }
            }
        })
    </script>

</body>

</html>

关注的问题: 我们发现,在元素属性赋值使用数据对象会失效

1
<td><a href="\{\{driver_config.root_url\}\}"></td>

这里其实就需要使用我们vue的特定语法了,见下章:vue指令

vue指令

内容绑定、事件绑定

v-text指令和插值表达式{{}}

  • v-text表达式会替换标签内部的所有内容,如果部分替换,推荐使用{{}}`
  • v-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
25
26
27
28
<body>
    <!-- el挂载的元素内部,可以使用声明的数据,外部不行 -->
    <!-- 1.内容替换 -->
    <!-- 2.字符串拼接 -->
    <div id="app">
        <p v-text="my_net_disk_name">阿里云</p>
        <p v-text="driver_config.name +'前进四'">那里不是家</p>
        <p>\{\{driver_config.type + "yyds"\}\}那里不是家</p>
    </div>
    

    <script>
        var app = new Vue({
            el: "#app",
            data: {
                my_net_disk_name: "my_net_disk",
                driver_config: {
                    id: 1,
                    name: "蓝色空间号",
                    type: "阿里云存储",
                    root_url: "www.flameking.com",
                    files: ["葵花宝典", "降龙十八掌", "如来神掌", "狮吼功"]
                }
            }
        })
    </script>

</body>

v-text和v-html

  • v-html指令的作用是:设置元素对象的innerHTML属性,内容中有html结构会被解析为标签
  • v-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
25
<body>
    <!-- el挂载的元素内部,可以使用声明的数据,外部不行 -->
    <div id="app">
        <p v-text="driver_config.root_url"></p>
        <p v-html="driver_config.root_url"></p>
    </div>
    

    <script>
        var app = new Vue({
            el: "#app",
            data: {
                my_net_disk_name: "my_net_disk",
                driver_config: {
                    id: 1,
                    name: "蓝色空间号",
                    type: "阿里云存储",
                    root_url: "<a href='www.flameking.com'>我的根目录</a>",
                    files: ["葵花宝典", "降龙十八掌", "如来神掌", "狮吼功"]
                }
            }
        })
    </script>

</body>

v-on指令

  • v-on指令是为元素绑定事件
  • 指令可简写为@
  • 绑定的事件函数定义在methods属性中
  • 函数内部必须通过this引用data中的数据对象,否则无法引用
  • 如果事件函数逻辑简单,比如仅仅一条表达式,那么就可以直接写在v-on:click='表达式'
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
<body>
    <!-- el挂载的元素内部,可以使用声明的数据,外部不行 -->
    <div id="app">
        <input type="button" value="做菜" v-on:click="doliaoli">
        <input type="button" value="双击获取小红花" @dblclick="redflower">
        <h1></h1>
        <h1>你已经获取8朵小红花</h1>
    </div>
    

    <script>
        var app = new Vue({
            el: "#app",
            data: {
                action: "西红柿炒蛋",
                count: 0
            },
            methods: {
                doliaoli:function(){
                    this.action+="好好吃!";
                    console.log(this.action);
                },
                redflower: function(){
                    alert("送你一朵小红花");
                    // 如果不用this修饰,无法引用数据对象
                    this.count++;
                }
            }
        })
    </script>

</body>
v-on指令自定义传参和事件修饰符

1.当事件函数带上了形参,那么传实参时就形如:v-on=”doliaoli(‘好吃’)”

2.事件的后面跟上.修饰符可以对事件进行限制

3..enter可以限制触发的按键为回车

4.事件修饰符有多种,详细可查阅

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
<body>
    <!-- el挂载的元素内部,可以使用声明的数据,外部不行 -->
    <div id="app">
        <button @click="doliaoli(dishName[index])">做菜</button>
        <button @click="prepareDish">准备其他菜品</button><br>

        <input type="text" value="请输入消息" @keyup.enter="enter">
    </div>
    

    <script>
        var app = new Vue({
            el: "#app",
            data: {
                dishName: ["西红柿炒蛋","辣椒炒肉","剁椒鱼头","麻婆豆腐"],
                index: 0
            },
            methods: {
                doliaoli: function(dishName){
                    alert("你刚刚做了一道" + dishName);
                },
                prepareDish: function(){
                    this.index = (this.index+1)%this.dishName.length;
                    console.log(this.index);
                },
                enter: function(){
                    console.log('消息已发送');
                }
            }
        })
    </script>

</body>

计数器案例

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
body{
  background-color: #f5f5f5;
}
#app {
  width: 480px;
  height: 80px;
  margin: 200px auto;
}
.input-num {
  margin-top:20px;
  height: 100%;
  display: flex;
  border-radius: 10px;
  overflow: hidden;
  box-shadow: 4px 4px 4px #adadad;
  border: 1px solid #c7c7c7;
  background-color: #c7c7c7;
}
.input-num button {
  width: 150px;
  height: 100%;
  font-size: 40px;
  color: #ad2a27;
  cursor: pointer;
  border: none;
  outline: none;
  background-color:rgba(0, 0, 0, 0);
}
.input-num span {
  height: 100%;
  font-size: 40px;
  flex: 1;
  text-align: center;
  line-height: 80px;
  font-family:auto;
  background-color: white;
}
img{
  float: right;
  margin-top: 50px;
}
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>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>计数器</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
    <link rel="stylesheet" href="./css/index.css">
</head>

<body>
    <!-- el挂载的元素内部,可以使用声明的数据,外部不行 -->
    <div id="app">
        <div class="input-num">
            <button @click="sub">-</button>
            <span>\{\{count\}\}</span>
            <button @click="add">+</button>
        </div>
    </div>
    
    <script>
        var app = new Vue({
            el: "#app",
            data: {
                count: 0
            },
            methods: {
                add: function () {
                    if (this.count < 10) {
                        ++this.count;
                    } else {
                        alert("兄弟,最大不过10");
                    }
                },
                sub: function () {
                    if (this.count > 0) {
                        --this.count;
                    } else {
                        alert("兄弟,最小不过0");
                    }
                }
            }
        })
    </script>

</body>

</html>

显示切换、属性绑定

v-show

  • v-show指令作用是:根据真假切换元素的显示状态,实际原理为设置css属性display: none,实现元素的隐藏
  • 指令后面的内容,最终都会解析为布尔值
  • v-show=”true”,元素显示;v-show=”false”,元素隐藏
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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
    <style>
        #app {
            width: 480px;
            height: 80px;
            margin: 200px auto;
        }

        /* .hp {
            margin-top: 20px;
            height: 100%;
            display: flex;
            border-radius: 10px;
            overflow: hidden;
            box-shadow: 4px 4px 4px #adadad;
            border: 1px solid #c7c7c7;
            background-color: #c7c7c7;
        } */

        div.hp {
            width: 500px;
            height: 100%;
            font-size: 20px;
            color: #ad2a27;
            cursor: pointer;
            border: none;
            outline: none;
            background-color: rgba(0, 0, 0, 0);
        }

        div span {
            font-size: 50px;
        }
    </style>
</head>

<body>
    <!-- el挂载的元素内部,可以使用声明的数据,外部不行 -->
    <div id="app">
        <div class="hp">
            <img v-show="HP" src="./img/艾莉丝-无职转生.jpg">
            <h1>心魔的血量还剩</h1>
            <br>
            <span></span>
            <h1 v-show="HP">各方道友,我快抵挡不住诱惑了,点击下方按钮助我击败心魔</h1>
            <button @click="suppress" v-text="button_content"></button>
        </div>
    </div>


    <script>
        var app = new Vue({
            el: "#app",
            data: {
                HP: 10,
                button_content: "齐心协力击败心魔"
            },
            methods: {
                suppress: function () {
                    if (this.HP > 0) {

                        --this.HP;
                    }

                    if (this.HP <= 2) {
                        console.log("心魔即将消灭!道友再加把力!");
                    }

                    if (this.HP == 0) {
                        alert("心魔已被击败,感谢道友的助力\n道友可就此打住");
                        this.button_content = "心魔已经被打败";
                    }

                }
            }
        })
    </script>

</body>

</html>

从这段程序可见,v-show把值大于0的一切整数解析为true,0则解析为false

v-show和v-if

v-if显示效果和使用方式与v-show并无区别,不过两者在dom操作底层上有本质区别,v-if表达式为false时,整个元素会从dom树结构移除,而v-show元素一直存在

显然v-if效率更低,如果元素需要频繁切换不推荐使用v-if

v-bind

v-bind用于专门操作元素内部属性,完整写法是v-bind:属性名,简写即:属性名,v-bind可直接省略,经绑定后的属性可以使用data数据对象中的值

常见应用:需要动态的增删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
39
40
41
42
43
44
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
    <style>
        a.active {
            font-size: 50px;
        }
    </style>
</head>
<body>
    <!-- el挂载的元素内部,可以使用声明的数据,外部不行 -->
    <div id="app">
        <!-- v-bind操作元素属性 -->
        <!-- 1.被v-bind修饰的元素内部属性可以使用data数据对象 -->
        <!-- 2.经典应用,操作class属性显示样式 -->

        <!-- 对象方式 :class="{active:isActive}" 读作class属性active的存在取绝isActive的值 -->
        <a :href="my_blog_url" target="_blank" :class="{active: isActive}">我的博客</a>
        <br>
        <button @click="vary_size">改变大小</button>
    </div>
    

    <script>
        var app = new Vue({
            el: "#app",
            data: {
                my_blog_url: "https://Casflawed.github.io",
                isActive: true
            },
            methods: {
                vary_size:function(){
                    this.isActive = !this.isActive;
                }
            }
        })
    </script>

</body>
</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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
* {
  margin: 0;
  padding: 0;
}

html,
body,
#mask {
  width: 100%;
  height: 100%;
}

#mask {
  background-color: #c9c9c9;
  position: relative;
}

#mask .center {
  position: absolute;
  background-color: #fff;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  padding: 10px;
}
#mask .center .title {
  position: absolute;
  display: flex;
  align-items: center;
  height: 56px;
  top: -61px;
  left: 0;
  padding: 5px;
  padding-left: 10px;
  padding-bottom: 0;
  color: rgba(175, 47, 47, 0.8);
  font-size: 26px;
  font-weight: normal;
  background-color: white;
  padding-right: 50px;
  z-index: 2;
}
#mask .center .title img {
  height: 40px;
  margin-right: 10px;
}

#mask .center .title::before {
  content: "";
  position: absolute;
  width: 0;
  height: 0;
  border: 65px solid;
  border-color: transparent transparent white;
  top: -65px;
  right: -65px;
  z-index: 1;
}

#mask .center > img {
  display: block;
  width: 700px;
  height: 458px;
}

#mask .center a {
  text-decoration: none;
  width: 45px;
  height: 100px;
  position: absolute;
  top: 179px;
  vertical-align: middle;
  opacity: 0.5;
}
#mask .center a :hover {
  opacity: 0.8;
}

#mask .center .left {
  left: 15px;
  text-align: left;
  padding-right: 10px;
  border-top-right-radius: 10px;
  border-bottom-right-radius: 10px;
}

#mask .center .right {
  right: 15px;
  text-align: right;
  padding-left: 10px;
  border-top-left-radius: 10px;
  border-bottom-left-radius: 10px;
}

img.display_img{
  width: 620px;
  height: 349px;
}
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
49
50
51
52
53
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>图片切换</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
    <link rel="stylesheet" href="./css/toggle_img.css">
</head>

<body>
    <div id="mask">
        <div class="center">
            <img class="display_img" :src="imgs[index]" alt="">
            <!-- v-if 如果操作img元素则会出错 -->
            <a v-if="index>0" @click="left" class="left"><img src="./img/prev.png" alt=""></a>
            <!-- 数组可以调用imgs.length,可见data数据对象依然符合JavaScript语法 -->
            <a v-if="index<imgs.length-1" @click="right" class="right"><img src="./img/next.png" alt=""></a>
        </div>
    </div>


    <script>
        var app = new Vue({
            el: "#mask",
            data: {
                index: 0,
                left_display: false,
                right_display: true,
                imgs: ["./img/01.png","./img/02.jpg","./img/03.jpg","./img/04.jpg","./img/05.jpg"]
            },
            methods: {
                left: function(){
                    if(this.index == 0){
                        this.index = 4;
                    }else{
                        this.index--;
                    }
                },
                right: function(){
                    if(this.index == 4){
                        this.index = 0;
                    }else{
                        this.index++;
                    }
                }
            }
        })
    </script>

</body>

</html>

列表循环、表单元素绑定

v-for指令

根据数据循环生成dom元素列,类比JSP模板引擎中的c:foreach标签,语法是v-for="(item,index) in arr",item和index可以结合其他指令一起使用。

数组经常和v-for结合使用,并且数组长度的更新会同步到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
<body>
    <!-- el挂载的元素内部,可以使用声明的数据,外部不行 -->
    <div id="app">
        <ul>
            <li v-for="(item,index) in items">\{\{item\}\}+\{\{index\}\}</li>
            <button @click="add">添加</button>
            <button @click="shift">删除</button>
        </ul>
    </div>

    <script>
        var app = new Vue({
            el: "#app",
            data: {
                items: [1, 2, 3, 4, 5]
            },
            methods: {
                add: function () {
                    this.items.push("6");
                },
                shift: function(){
                    this.items.shift();
                }
            }
        })
    </script>

</body>

v-model指令

能把表单中的值和挂载实例中的数据关联起来,这样可以十分便捷的获取、设置表单元素的值(双向绑定,指更改任何一方,都会同步更新)

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
<body>
    <!-- el挂载的元素内部,可以使用声明的数据,外部不行 -->
    <div id="app">
        <button @click="setMsg">修改输入框</button>
        <input type="text" v-model="msg" @keyup.enter="getMsg">
    </div>
    

    <script>
        var app = new Vue({
            el: "#app",
            data: {
                msg: "对数器"
            },
            methods: {
                getMsg: function(){
                    alert(this.msg);
                },
                setMsg: function(){
                    this.msg = "局部最小量";
                }
            }
        })
    </script>

</body>

记事本案例

0.显示带索引的任务列表,v-for,和插值表达式展示item和index

1.添加任务,v-model让数据对象和输入框值双向绑定,v-on绑定keyup.enter事件,将数据添加进数组

2.删除任务,v-on,数组list.splice(index,count),从index位置删除count个元素

3.统计元素个数

4.清空数组元素,list = []

5.隐藏清空后列表的显示效果,使用v-show=”list.length>0”

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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
<html>

<head>
  <title>小黑记事本</title>
  <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
  <meta name="robots" content="noindex, nofollow" />
  <meta name="googlebot" content="noindex, nofollow" />
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <link rel="stylesheet" type="text/css" href="./css/notebook.css" />
</head>

<body>
  <!-- 主体区域 -->
  <section id="todoapp">
    <!-- 输入框 -->
    <header class="header">
      <h1>小黑记事本</h1>
      <input v-model="inputValue" @keyup.enter="add" autofocus="autofocus" autocomplete="off" placeholder="请输入任务"
        class="new-todo" />
    </header>
    <!-- 列表区域 -->
    <section class="main">
      <ul class="todo-list">
        <li class="todo" v-for="(item,index) in list">
          <div class="view">
            <span class="index">.</span>
            <label></label>
            <button class="destroy" @click="remove(index)"></button>
          </div>
        </li>
      </ul>
    </section>
    <!-- 统计和清空 -->
    <footer v-show="list.length>0" class="footer" >
      <span class="todo-count">
        <strong></strong> items left
      </span>
      <button class="clear-completed" @click="clear">
        Clear
      </button>
    </footer>
  </section>
  <!-- 底部 -->
  <!-- <footer class="info">
    <p>
      <a href="http://www.itheima.com/"><img src="./img/black.png" alt="" /></a>
    </p>
  </footer> -->
  <!-- 开发环境版本,包含了有帮助的命令行警告 -->
  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  <script>
    var app = new Vue({
      el: "#todoapp",
      data: {
        list: [],
        inputValue: "好好学习,天天向上",
        isActive: false
      },
      methods: {
        add: function () {
          this.list.push(this.inputValue);
          this.inputValue = "";
        },
        remove:function(index){
          this.list.splice(index,1);
        },
        clear:function(){
          this.list = [];
        }
      },
    })
  </script>
</body>

</html>

axios网络应用

axios是封装Ajax后的产物,它相比Ajax更加易用,功能更加单一,就是发送网络请求

axios发送get请求

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
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>axios get请求</title>
    <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>

<body>
    <!-- el挂载的元素内部,可以使用声明的数据,外部不行 -->
    <div id="app">
        <button @click="getJoke">获取随机笑话</button>
        <p>\{\{joke\}\}</p>
    </div>
    

    <script>
        var app = new Vue({
            el: "#app",
            data: {
                joke:''
            },
            methods: {
                getJoke:function(){
                    // 两个函数内部使用this的含义不同
                    var obj = this;
                    axios.get("https://autumnfish.cn/api/joke")
                    .then(function(response){
                        obj.joke = response.data;
                    })
                    .catch(function(error){
                        console.log('错误码:' + error.status + ',错误消息:' + error.statusText);
                    })
                }
            }
        })
    </script>

</body>

</html>

1.axios回调函数中的this并不是Vue实例对象,这个this是无法访问到data中的数据,解决办法时将代表Vue实例的this用变量存储起来,延长作用域,这样就可以在axios回调函数中使用

2.axios网络应用和本地应用最大的区别就是改变了数据来源,原来都是本地生成的数据,而现在使用请求响应的数据

天知道网络案例

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
49
50
51
52
53
54
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <meta http-equiv="X-UA-Compatible" content="ie=edge" />
  <title>天知道</title>
  <link rel="stylesheet" href="./css/weather_reset.css" />
  <link rel="stylesheet" href="./css/weather_index.css" />
</head>

<body>
  <div class="wrap" id="app">
    <div class="search_form">
      <div class="logo"><img src="./img/logo.png" alt="logo" /></div>
      <div class="form_group">
        <input type="text" v-model="city"  @keyup.enter="searchWeather"   class="input_txt" placeholder="请输入查询的天气"/>
        <button class="input_sub" @click="searchWeather">
          搜 索
        </button>
      </div>
      <div class="hotkey">
        <a href="javascript:;" @click="changeCity('北京')">北京</a>
        <a href="javascript:;" @click="changeCity('上海')">上海</a>
        <a href="javascript:;" @click="changeCity('广州')">广州</a>
        <a href="javascript:;" @click="changeCity('深圳')">深圳</a>
      </div>
    </div>
    <ul class="weather_list">
      <li v-for="item in weatherList">
        <div class="info_type">
            <span class="iconfont"></span>
        </div>
        <div class="info_temp">
          <b></b>
          ~
          <b></b>
        </div>
        <div class="info_date">
            <span></span>
        </div>
      </li>
    </ul>
  </div>
  <!-- 开发环境版本,包含了有帮助的命令行警告 -->
  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  <!-- 官网提供的 axios 在线地址 -->
  <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
  <!-- 自己的js -->
  <script src="./js/main.js"></script>
</body>

</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
var app = new Vue({
    el: "#app",
    data: {
        city: '衡阳',
        weatherList: []
    },
    methods:{
        searchWeather: function(){
            var main = this;
            axios.get("http://wthrcdn.etouch.cn/weather_mini?city=" + this.city)
            .then(function(response){
                main.weatherList = response.data.data.forecast;
                // 查看控制台会发现,这条打印语句最后才会打印,毕竟是网络请求速度会要慢些
                console.log(main.weatherList);
            })
            console.log(this.city);
        },
        changeCity: function(city){
            this.city = city;
            this.searchWeather();
        }
    }

})

Vue实例在methods方法内部通过this表示,类比Java类,this其实就是对象,而data就是属性或者说字段,el就是构造函数,methods就是方法,那么这些元素都可以通过this.的方法调用,如this.searchWeather(),就表现为方法searchweather方法被调用。

悦听player

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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <meta http-equiv="X-UA-Compatible" content="ie=edge" />
  <title>悦听player</title>
  <!-- 样式 -->
  <link rel="stylesheet" href="./css/player/index.css">
</head>

<body>
  <div class="wrap">
    <!-- 播放器主体区域 -->
    <div class="play_wrap" id="player">
      <div class="search_bar">
        <img src="./img/player/player_title.png" alt="" />
        <!-- 搜索歌曲 -->
        <input type="text" autocomplete="off" v-model="query" @keyup.enter="searchSongs" />
      </div>
      <div class="center_con">
        <!-- 歌曲列表 -->
        <div class='song_wrapper'>
          <ul class="song_list">
            <li v-for="(item,index) in songs">
              <a href="javascript:;" @click="playSong(index)"></a> 
              <b></b> 
              <!-- 显示mv图标 -->
              <span><i v-show="item.mvid>0" @click="playMV(item.mvid)"></i></span>
            </li>
          </ul>
          <img src="./img/player/line.png" class="switch_btn" alt="">
        </div>
        <!-- 歌曲信息容器 -->
        <div class="player_con" :class="{playing:isPlaying_song}">
          <img src="./img/player/player_bar.png" class="play_bar" />
          <!-- 黑胶碟片 -->
          <img src="./img/player/disc.png" class="disc autoRotate" />
          <!-- 歌曲封面 -->
          <img :src="songCover" class="cover autoRotate" />
        </div>
        <!-- 评论容器 -->
        <div class="comment_wrapper">
          <h5 class='title'>热门留言</h5>
          <div class='comment_list'>
            <dl v-for="item in songHotComments">
              <!-- 用户头像 -->
              <dt><img :src="item.user.avatarUrl" alt=""></dt>
              <!-- 用户昵称 -->
              <dd class="name"></dd>
              <!-- 用户评论 -->
              <dd class="detail">
                
              </dd>
            </dl>
          </div>
          <img src="./img/player/line.png" class="right_line">
        </div>
      </div>
      <div class="audio_con">
        <!-- 音频播放器 -->
        <audio ref='audio' :src="songUrl" @pause="doPause_song" @playing="doPlaying_song" controls autoplay loop class="myaudio"></audio>
      </div>
      <div class="video_con" v-show="isShow_mv">
        <!-- 视频播放器 -->
        <video :src="mvUrl" controls="controls"></video>
        <div class="mask" @click="hide"></div>
      </div>
    </div>
  </div>
  <!-- 开发环境版本,包含了有帮助的命令行警告 -->
  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  <!-- 官网提供的 axios 在线地址 -->
  <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
  <script src="./js/player_main.js"></script>
</body>

</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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
/*
  1:歌曲搜索接口
    请求地址:https://autumnfish.cn/search
    请求方法:get
    请求参数:keywords(查询关键字)
    响应内容:歌曲搜索结果

  2:歌曲url获取接口
    请求地址:https://autumnfish.cn/song/url
    请求方法:get
    请求参数:id(歌曲id)
    响应内容:歌曲url地址
  3.歌曲详情获取
    请求地址:https://autumnfish.cn/song/detail
    请求方法:get
    请求参数:ids(歌曲id)
    响应内容:歌曲详情(包括封面信息)
  4.热门评论获取
    请求地址:https://autumnfish.cn/comment/hot?type=0
    请求方法:get
    请求参数:id(歌曲id,地址中的type固定为0)
    响应内容:歌曲的热门评论
  5.mv地址获取
    请求地址:https://autumnfish.cn/mv/url
    请求方法:get
    请求参数:id(mvid,为0表示没有mv)
    响应内容:mv的地址
*/
var app = new Vue({
  el: "#player",
  data: {
    // 查询关键字
    query:'',
    // 歌曲数组
    songs:[],
    // 歌曲地址
    songUrl:'',
    // 歌曲封面
    songCover:'',
    // 歌曲评论
    songHotComments:[],
    // 动画播放状态
    isPlaying_song:false,
    // 正在播放歌曲的索引
    songId:-1,
    // 遮罩层的显示状态
    isShow_mv:false,
    // mv地址
    mvUrl:''
  },
  methods: {
    // 1.搜索歌曲,初始化歌曲数组
    searchSongs:function(){
      var main = this;
      axios.get("https://autumnfish.cn/search?keywords="+this.query)
      .then(function(response){
        main.songs = response.data.result.songs;
        console.log(response);
      })
      .catch(function(error){})
    },

    // 2.播放歌曲
    playSong:function(index){
      // 2-0.避免正在播放的歌曲信息被反复请求
      if(this.songs[index].id == this.songId){
        return;
      }
      // 2-1.初始化歌曲id
      console.log("歌曲索引:"+index);
      this.songId = this.songs[index].id;
      console.log("歌曲id:"+this.songId);

      var main = this;
      
      // 2-2.初始化歌曲url
      axios.get("https://autumnfish.cn/song/url?id="+this.songId)
      .then(function(response){
        main.songUrl = response.data.data[0].url;
        console.log("歌曲url:"+response.data.data[0].url);
      }).catch(function(error){})

      // 2-3.初始化歌曲封面
      axios.get("https://autumnfish.cn/song/detail?ids="+this.songId)
      .then(function(response){
        main.songCover = response.data.songs[0].al.picUrl;
        console.log("封面url:"+response.data.songs[0].al.picUrl);
      })
      .catch(function(error){
        alert(error);
      })

      // 2-4.初始化热评信息
      axios.get("https://autumnfish.cn/comment/hot?type=0&id="+this.songId)
      .then(function(response){
        main.songHotComments = response.data.hotComments;
        console.log(response.data.hotComments);
      }).catch(function(error){})
    },

    // 3.歌曲播放状态
    doPlaying_song:function(){
      console.log("song播放");
      this.isPlaying_song = true;
    },

    // 4.歌曲暂停状态
    doPause_song:function(){
      console.log("song暂停");
      this.isPlaying_song = false;

    },

    // 5.播放mv
    playMV:function(mvId){
      
      var main = this;
      axios.get("https://autumnfish.cn/mv/url?id="+mvId)
      .then(function(response){
        console.log("mvUrl:"+response.data.data.url);
        // 5-1.初始化mvUrl
        main.mvUrl = response.data.data.url;

        // 5-2.打开遮罩层
        main.isShow_mv = true;

        // 5-3.暂停正在播放的歌曲
        main.$refs.audio.pause();

      }).catch(function(){})
    },

    // 6.隐藏遮罩层
    hide:function(){
      // 6-1.关闭遮罩层
      this.isShow_mv = false;
      // 6-2.关闭mv
      this.mvUrl = '';
    }

  }
});
本文由作者按照 CC BY 4.0 进行授权