0%

第十天

第十三天

vue-resource改造品牌列表案例

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
<!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>vue-resource改造品牌列表案例</title>
<script src="./js/vue.js"></script>
<script src="./js/vue-resource.js"></script>
<style>
#app th,
td {
border: 1px solid #000;
}

#app thead th {
width: 200px;
}

#app tbody td {
width: 200px;
text-align: center;
}
</style>
</head>

<body>
<div id="app">
<div>
<label for="">Name: <input type="text" v-model="name"></label>
<input type="button" value="添加" @click="add">
</div>
<table>
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>Ctime</th>
<th>Operation</th>
</tr>
</thead>
<tbody>
<tr v-for="item in list" :key="item.id">
<td>{{item.id}}</td>
<td>{{item.name}}</td>
<td>{{item.ctime}}</td>
<td><a href="" @click.prevent="del(item.id)">删除</a></td>
</tr>
</tbody>
</table>
</div>
<script>
var vm = new Vue({
el: "#app",
data: {
name: '',
list: []
},
created() {
this.getAllList();
},
methods: {
getAllList() {
//获取所有车的列表
// 分析:
// 1. 由于已经导入了 Vue-resource包,可以直接通过this.$http 来发起数据请求
// 2. 根据接口API文档,获取列表时应该发起一个get请求
// 3. this.$http.get('url').then(function(result){})
// 4. 当通过then 指定回调函数后,在回调函数可以拿到数据服务器返回的result
// 5. 先判断result.status是否等于0,如果等于0,就成功了,可以把result.message赋值给this.list;如果不等于0,可以提示获取数据失败
this.$http.get('http://localhost:8080/Vue/get').then(result => {
console.log(result.body);
// 注意:通过$http获取到的数据,都在result.body中放着
var result = result.body;
if (result.status === 0) {
this.list = result.message;
} else {
alert('获取数据失败')
}
});
},
add() {
// 添加到后台服务器
// 分析
// 1. 经过查看api接口, 发现要发送一个post请求, this.$http.post
// 2. this.$http.post() 中接收三个参数
// 第一个参数:要请求的URL地址
// 第二个参数:要提交给服务器的数据,要以对象形式提交给服务器
// 第三个参数:一个配置对象,要以哪种表单数据类型提交{emulateJSON:true},以普通表单格式,将数据提交给服务器application/x-www-form-urlencoded
// 3.在post方法中,使用.then来设置成功的回调函数,如果想要拿到成功的结果,需要result.body
this.$http.post("http://localhost:8080/Vue/add", {
name: this.name
}, {
emulateJSON: true
}).then(result => {
console.log(result.body);
if (result.body.status === 0) {
// 成功
this.getAllList();
} else {
alert("添加失败")
}
})
},
del(id) {
this.$http.get('http://localhost:8080/Vue/del?id=' + id).then(result => {
if (result.body.status === 0) {
this.getAllList();
} else {
alert("删除失败");
}
});
}
}
});
</script>
</body>

</html>

全局配置域名根路径和全局启用emulateJSON

1
2
3
4
5
6
 // 如果我们通过全局配置了根域名,请求的数据接口根域名,则每次单独发起http请求的时候,请求的url路径,应该以相对路径开头,前面不能带/,否则,不会启用根路径拼接
Vue.http.options.root = "http://localhost:8080";
// 全局启用emulateJSON 选项
Vue.http.options.emulateJSON = true;
...
this.$http.get('Vue/get').then();

动画

使用过渡类名实现动画

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
<!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>
<script src="./js/vue.js"></script>
<style>
/* 2. 自定义两级样式,来控制transition内部的元素实现动画 */
/* v-enter[一个时间点]:进入之前,元素的起始状态,此时还没有开始进入 */
/* .v-leave-to[一个时间点]:动画离开的终止状态,此时,元素动画已经结束 */

.v-enter,
.v-leave-to {
opacity: 0;
/* 从右进入 */
transform: translateX(80px);
}

/* v-enter-active[入场动画的时间段] */
/* .v-leave-active[离场动画的时间段]*/
.v-enter-active,
.v-leave-active {
transition: all 0.4s ease;
}
</style>
</head>

<body>
<div id="app">
<input type="button" value="toggle" @click="flag=!flag">
<!-- 需求:点击按钮,让h3显示,再点击,让h3隐藏(过程渐变) -->
<!-- 1. 使用transition元素,把需要被动画控制的元素包裹起来 -->
<!-- transition元素,是Vue官方提供的 -->
<transition name="" mode="">
<h3 v-if="flag">这是一个h3</h3>
</transition>

</div>
<script>
var vm = new Vue({
el: "#app",
data: {
flag: false
}
})
</script>
</body>

</html>

修改v-前缀

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>
<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>修改v-前缀</title>
<script src="./js/vue.js"></script>
<style>
.my-enter,
.my-leave-to {
opacity: 0;
transform: translateY(70px);
}

.my-enter-active,
.my-leave-active {
transition: all 0.4s ease;
}
</style>
</head>

<body>
<div id="app">
<input type="button" value="toggle" @click="flag=!flag">
<transition name="my" mode="">
<h6 v-if="flag">这是一个h6</h6>
</transition>
<script>
var vm = new Vue({
el: "#app",
data: {
flag: false
}
})
</script>
</div>
</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
<!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>
<script src="./js/vue.js"></script>
<link rel="stylesheet" href="./animate.css">
</head>

<body>
<div id="app">
<input type="button" value="toggle" @click="flag=!flag">
<!-- duration:"毫秒值" 统一设置入场和离场时动画时间 -->
<!-- duration="{enter:毫秒值,leave:毫秒值}" 分别设置入场和离场时间 -->
<transition enter-active-class="animated bounceIn" leave-active-class="animated bounceOut" :duration="200">
<h6 v-if="flag">这是一个h6</h6>
</transition>
<script>
var vm = new Vue({
el: "#app",
data: {
flag: false
}
})
</script>
</div>
</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
<!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>
<script src="./js/vue.js"></script>
<style>
.ball {
width: 15px;
height: 15px;
border-radius: 50%;
background-color: red;
}
</style>
</head>

<body>
<div id="app">
<input type="button" value="加入购物车" @click="flag=!flag">
<!-- 1. 使用transition元素把小球包裹起来 -->
<transition @before-enter="beforeEnter" @enter="enter" @after-enter="afterEnter">
<div class="ball" v-show="flag"></div>
</transition>
</div>
<script>
var vm = new Vue({
el: "#app",
data: {
flag: false
},
methods: {
// 注意:动画钩子函数的第一个参数:el,表示要执行动画的那个DOM元素是个原生的JS DOM对象,可以认为是通过document.getElementByID()获取到的
beforeEnter(el) {
// 表示动画入场之前,此时动画尚未开始,可以在此处设置元素开始动画之前的起始样式
el.style.transform = "translate(0,0)"; //设置小球开始动画之前的起始位置
},
enter(el, done) {
// 这句话,没有实际作用,但如果不写,出不来动画效果;
// 可以认为el.offsetWidth 会强制动画刷新
el.offsetWidth
// 表示动画开始之后的样式,此处可以设置小球完成动画之后的结束状态
el.style.transform = "translate(150px,450px)";
el.style.transition = "all 1s ease";

// 这里的done,其实就是afterEnter函数,也就是说done是afterEnter的引用
done(); //动画完成后立即消失
},
afterEnter(el) {
// 动画完成之后,会调用afterEnter
this.flag = false;
}
}
});
</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
<!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>
<script src="./js/vue.js"></script>
<style>
li {
border: 1px dashed #999;
margin: 5px;
line-height: 35px;
padding-left: 5px;
font-size: 12px;
width: 100%;
}

li:hover {
background-color: pink;
transition: all 0.8s ease;
}

.v-enter,
.v-leave-to {
opacity: 0;
transform: translateY(80px);
}

.v-enter-active,
.v-leave-active {
transition: all 0.6s ease;
}

/* .v-move 和 .v-leave-active 配合使用能够实现列表后续的元素渐渐地漂上来的效果 */
.v-move {
transition: all 0.6s ease;
}

.v-leave-active {
position: absolute;
}
</style>
</head>

<body>
<div id="app">
<div>
<label for="">Id: <input type="text" v-model="id"></label>
<label for="">Name: <input type="text" v-model="name"></label>
<input type="button" value="添加" @click="add">
</div>

<!-- 在实现列表过渡时,如果需要过渡的元素,是通过v-for循环渲染的,不能使用transition包裹,需要使用transitionGroup -->
<!-- 如果要为v-for循环创建的元素设置动画,必须为每一个元素设置:key属性 -->
<!-- 给transition-group 添加appear属性,实现页面刚展示出来的效果 -->
<!-- 通过为transition-group元素,设置tag属性,指定transition-group渲染为指定的元素,如果不指定tag属性,默认渲染为span标签 -->
<transition-group appear tag="ul">
<li v-for="(item,i) in list" :key="item.id" @click="del(i)">{{item.id}}--{{item.name}}</li>
</transition-group>


</div>
<script>
var vm = new Vue({
id: '',
name: '',
el: "#app",
data: {
list: [{
id: 1,
name: 'zs'
}, {
id: 2,
name: 'ls'
}, {
id: 3,
name: 'ww'
}]
},
methods: {
add() {
this.list.push({
id: this.id,
name: this.name
});
this.id = this.name = "";
},
del(i) {
this.list.splice(i, 1);
}
}
})
</script>
</body>

</html>

组件

什么是组件

组件的出现,就是为了拆分Vue实例的代码量的,能够让我们以不同的组件,来划分不同的功能模块,将来我们需要什么样的功能,就可以去调用对应的组件即可

组件化和模块化的不同

模块化:是从代码逻辑的角度进行划分,方便代码分层开发,保证每个功能模块的职能单一 组件化:是从UI界面的角度进行划分,前端的组件化,方便UI组件的重用

全局组件定义的三种方式

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
<!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>
<script src="./js/vue.js"></script>
</head>

<body>
<div id="app">
<!-- 如果要使用组件,直接把组件的名称,以HTML标签的形式引入到页面中即可 -->
<my-com1>

</my-com1>
<!-- 还是以标签的形式引入 -->
<my-com2></my-com2>
<my-com3></my-com3>
</div>
<!-- 在控制的#app外面,使用template元素定义组件的HTML模板结构 -->
<template id="tmp1">
<div>
<h1>这是通过template元素,在外面定义的组件组件,这样有代码智能提示</h1><span>123</span>
</div>
</template>
<script>
// 1.1 使用Vue.extend来创建全局的Vue组件
var com1 = Vue.extend({
template: '<h3>这是用Vue.extend创建的组件 </h3>' //通过template属性,指定了组件要展示的HTML结构
})
// 1.2 使用Vue.component('组件的名称',创建出来的组件模板对象)
// 使用使用Vue.component定义全局组件时, 组件名称使用驼峰命名, 则在引用组件时, 需要将大写变小写, 并在单词间加 - 连接,如果不使用驼峰,则直接用名称即可
Vue.component('myCom1', com1);

// Vue.component 第一个参数: 组件的名称, 在引用组件时, 就是以标签形式来引入
// 第二个参数:Vue.extend创建的组件,其中template就是组件将来要展示的内容

// Vue.component('mycom1', Vue.extend({
// template: '<h3>这是用Vue...</h3>'
// }));

// 方式二
Vue.component('myCom2', {
// 注意:无论那种方式创建出来的组件,template属性指定的模板内容,必须有且只有唯一的一个根元素
template: '<div><h3>这是直接使用Vue.component创建出来的组件</h3><span>123</span></div>'
})

// 方式三
Vue.component("myCom3", {
template: "#tmp1"
});


var vm = new Vue({
el: "#app"
})
</script>
</body>

</html>

定义私有的组件

1
2
3
4
5
6
7
8
9
var vm = new Vue({
el: "#app",
// 定义实例内部私有组件
components: {
privateCom: {
template: "<h1>这是私有的自定义组件</h1>"
}
}
})

组件中的data和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
<!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>组件中的data和methods</title>
<script src="./js/vue.js"></script>
</head>

<body>
<div id="app">
<my-com1></my-com1>
</div>
<script>
// 1. 组件可以有自己的data数据
// 2. 组件的data和实例的data不一样,实例中的data可以为一个对象,但组件中的data必须是一个方法
// 3. 组件中的data除了必须是一个方法外,这个方法内部还必须返回一个对象
// 4. 组件中的data数据,使用方式和实例中的data使用方式完全一样
Vue.component('myCom1', {
template: '<h1>这是全局组件 --- {{msg}}</h1>',
data: function () {
return {
msg: '这是组件中data定义的数据'
}
}
});

var vm = new Vue({
el: "#app"
})
</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
<!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>
<script src="./js/vue.js"></script>
</head>

<body>
<div id="app">
<counter></counter>
<hr>
<counter></counter>
<hr>
<counter></counter>
</div>
<template id="tmp1">
<div>
<input type="button" value="+1" @click="increment">
<h3>{{count}}</h3>
</div>
</template>
<script>
var dataObj = {
count: 0
};
Vue.component('counter', {
template: '#tmp1',
data: function () {
// return dataObj; // 每次返回对象共享,当多个一起使用时会互相干扰
return {
count: 0
}
},
methods: {
increment() {
this.count++;
}
}
});
var vm = new Vue({
el: "#app"
});
</script>
</body>

</html>

使用components属性定义局部子组件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 创建 Vue 实例,得到 ViewModel
var vm = new Vue({
el: '#app',
data: {},
methods: {},
components: { // 定义子组件
account: { // account 组件
template: '<div><h1>这是Account组件{{name}}</h1><login></login></div>', // 在这里使用定义的子组件
components: { // 定义子组件的子组件
login: { // login 组件
template: "<h3>这是登录组件</h3>"
}
}
}
}
});

组件切换

方式一

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>
<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>
<script src="./js/vue.js"></script>
</head>

<body>
<div id="app">
<a href="" @click.prevent="flag=true">登录</a>
<a href="" @click.prevent="flag=false">注册</a>
<login v-if="flag"></login>
<register v-else="flag"></register>
</div>
<script>
Vue.component('login', {
template: '<h3>登录组件</h3>'
})
Vue.component('register', {
template: '<h3>注册组件</h3>'
})
var vm = new Vue({
el: '#app',
data: {
flag: false
}
})
</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
<!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>
<script src="./js/vue.js"></script>
</head>

<body>
<div id="app">
<!-- Vue提供了 component,来展示对应名称的组件 -->
<!-- component 是一个占位符,:is属性,可以用来指定要展示的组件的名称 -->
<a href="" @click.prevent="comName='login'">登录</a>
<a href="" @click.prevent="comName='register'">注册</a>
<component :is="comName"></component>
</div>
<script>
// 组件名称是字符串
Vue.component('login', {
template: '<h3>登录组件</h3>'
})
Vue.component('register', {
template: '<h3>注册组件</h3>'
})
var vm = new Vue({
el: '#app',
data: {
comName: "login" // 当前component中的:is绑定的组件的名称
}
})
</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
<!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>
<script src="./js/vue.js"></script>
<style>
.v-enter,
.v-leave-to {
opacity: 0;
transform: translateX(150px);
}

.v-enter-active,
.v-leave-active {
transition: all 0.5s ease;
}
</style>
</head>

<body>
<div id="app">
<a href="" @click.prevent="comName='login'">登录</a>
<a href="" @click.prevent="comName='register'">注册</a>
<!-- 通过mode属性,设置组件切换时的方式 -->
<transition mode="out-in">
<component :is="comName"></component>
</transition>

</div>
<script>
// 组件名称是字符串
Vue.component('login', {
template: '<h3>登录组件</h3>'
})
Vue.component('register', {
template: '<h3>注册组件</h3>'
})
var vm = new Vue({
el: '#app',
data: {
comName: "login" // 当前component中的:is绑定的组件的名称
}
})
</script>
</body>

</html>