vue的生命周期及axios

生命周期

img

生命周期钩子函数

  • beforeCreate 创建之前(可以预加载)
  • created 创建完成(可以请求数据)
  • beforeMount 挂载之前 (可以对虚拟dom的优化)
  • mounted 挂载完成(可以阻止渲染)
  • beforeUpdate 修改之前 (可以阻止修改)
  • updated 修改完成 (可以进行修改完成的后续操作)
  • beforeDestroy 销毁之前(回收资源)
  • destroyed 销毁完成()
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
<div id="app">
<input type="text" v-model="names">
<h1>你好 {{names}}</h1>
<!-- <button @click="close">销毁</button> -->
</div>
<script src="./lib/vue.js"></script>
<script>
Vue.config.productionTip = false
const vm = new Vue({
el: '#app',
data: {
names: '袁同学!',
},
methods: {

},
// 若有template,则会直接渲染template,不会渲染el里的html元素
template:"<h3>hello world!</h3>",
beforeCreate() {
console.log('beforeCreate,创建之前');
},
created() {
console.log('created,创建完成');
},
beforeMount() {
console.log('beforeMount,挂载之前');
},
mounted() {
console.log('mounted,挂载完成');
},
beforeUpdate() {
console.log('beforeUpdate,更新之前');
},
updated() {
console.log('updated,更新完成');
},
beforeDestroy() {
console.log('beforeDestroy,销毁之前');
},
destroyed() {
console.log('beforeDestroy,销毁完成');
},
})

vue内置的网络请求

vue.resource(已废弃)

axios

Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中。

特性
  • 从浏览器中创建 XMLHttpRequests
  • 从 node.js 创建 http请求
  • 支持 Promise API
  • 拦截请求和响应
  • 转换请求数据和响应数据
  • 取消请求
  • 自动转换 JSON 数据
  • 客户端支持防御 XSRF

简易的用户管理系统

数据(user.json)
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
{
"users": [
{
"id": 1,
"username": "tom",
"avatar": "https://img2.baidu.com/it/u=2043310493,2206067123&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=500",
"email": "nobita@qq.com",
"age": "12",
"isEdit": true
},
{
"id": 2,
"username": "tom",
"avatar": "https://img2.baidu.com/it/u=2043310493,2206067123&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=500",
"email": "123@163.com",
"age": 22
},
{
"id": 3,
"username": "tom",
"avatar": "https://img2.baidu.com/it/u=2043310493,2206067123&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=500",
"email": "123@163.com",
"age": 22
},
{
"id": 4,
"username": "jerry",
"avatar": "https://img0.baidu.com/it/u=912844464,1907087211&fm=253&app=138&size=w931&n=0&f=PNG&fmt=auto?sec=1680109200&t=ad9a44000082b932d0cf48960b84b5ee",
"email": "123@163.com",
"age": 21
},
{
"id": 5,
"username": "jerry",
"avatar": "https://img0.baidu.com/it/u=912844464,1907087211&fm=253&app=138&size=w931&n=0&f=PNG&fmt=auto?sec=1680109200&t=ad9a44000082b932d0cf48960b84b5ee",
"email": "123@163.com",
"age": 21
}
]
}
1
2
预先在终端配置服务:
json-server -w .\user.json
代码
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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<!-- 最新版本的 Bootstrap 核心 CSS 文件 -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css"
integrity="sha384-HSMxcRTRxnN+Bdg0JdbxYKrThecOKuH5zCYotlSAcp1+c8xmyTe9GYg1l9a69psu" crossorigin="anonymous">
<style>
.saveBox {
width: 600px;
background-color: #ddd;
margin: 20px auto;
padding: 30px;
border-radius: 5px;
}

.showBox {
width: 1000px;
margin: 10px auto;
}

.showBox td img {
width: 30px;
height: 30px;
}
</style>
</head>

<body>
<!--

-->
<div id="app">
<!-- 添加用户 -->
<div class="saveBox">
<div class="form-group">
<label for="basic-url">usename</label>
<input type="text" class="form-control" v-model="user.username">
</div>
<div class="form-group">
<label for="basic-url">age</label>
<input type="text" class="form-control" v-model="user.age">
</div>
<div class="form-group">
<label for="basic-url">avatar</label>
<input type="text" class="form-control" v-model="user.avatar">
</div>
<div class="form-group">
<label for="basic-url">email</label>
<input type="text" class="form-control" v-model="user.email">
</div>
<button class="btn btn-default" type="submit" @click="saveUser">添加</button>
</div>
<!-- 用户列表 -->
<div class="showBox">
<div class="panel panel-default">
<!-- Default panel contents -->
<div class="panel-heading">Users</div>
<!-- Table -->
<table class="table">
<thead>
<tr>
<th>编号</th>
<th>用户名</th>
<th>年龄</th>
<th>头像</th>
<th>邮箱</th>
<th>操作</th>
</tr>
</thead>
<tbody v-for="(users,index) in users" ::key="users.id">
<tr v-if="!users.isEdit">
<td>{{index=1}}</td>
<td>{{users.username}}</td>
<td>{{users.age}}</td>
<td><img :src="users.avatar" alt=""></td>
<td>{{users.email}}</td>
<td>
<button class="btn btn-default" @click="users.isEdit=true">编辑</button>
<button class="btn btn-default" @click="deleteById(users.id)">删除</button>
</td>
</tr>
<tr v-else>
<td>{{index=1}}</td>
<td>
<input type="text" class="form-control" v-model="users.username">
</td>
<td>
<input type="text" style="width: 80px;" class="form-control" v-model="users.age">
</td>
<td>
<input type="text" class="form-control" v-model="users.avatar">
</td>
<td>
<input type="text" class="form-control" v-model="users.email">
</td>
<td>
<button class="btn btn-default" @click="updateById(users.id)">添加</button>
<button class="btn btn-default" @click="users.isEdit=false">取消更改</button>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<script src="./lib/vue.js"></script>
<script src="./lib/axios.min.js"></script>
<script>
Vue.config.productionTip = false
axios.defaults.baseURL = "http://localhost:3000/"
const vm = new Vue({
el: '#app',
data: {
users: [],
user: {
username: '',
age: '',
avatar: '',
email: ''
},
},
methods: {
async getUsers() {
let { data } = await axios.get("/users")
// 添加一个编辑的状态到对象中
data.forEach(user => {
user.isEdit = false
});
this.users = data
},
async deleteById(id) {
await axios.delete(`/users/${id}`)
this.getUsers()
},
async saveUser() {
if (this.check(this.user)) {
// 发送添加的请求
await axios.post("/users", this.user)
}
this.getUsers()
},
check(user) {
try {
Object.keys(user).forEach((key) => {
if (user[key].toString().trim() == '') {
throw new Error()
}
})
return true
} catch (err) {
alert('请将填写完整')
}
},
async updateById(id) {
let newUser = this.users.find((user) => {
return user.id == id
})
// 发送请求
if (this.check(newUser)) {
// 发送请求修改数据
await axios.put(`/users/${id}`, newUser)
newUser.isEdit = false
} else {
// 重新获取新的数据
this.getUsers()
}
}
},
beforeMount() {
this.getUsers()
},
})
</script>
</body>

</html>

自定义指令

vue官方提供了v-text、v-html、v-model、v-if等一些常用的指令。除此之外vue还允许开发者自定义指令。

规则

  • 使用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
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
<div id="app">
<h1 v-color:name="msg">你好 {{names}}</h1>
<h1 v-color:name="color">你好 {{names}}</h1>
<input v-placeholder="msg" type="text">
<div v-myhtml="htmlCode"></div>
</div>
<script src="./lib/vue.js"></script>
<script>
Vue.config.productionTip = false
// 全局自定义必须声明在vue实例之前
// 第一个为自定义指令的名字,第二个为对应的处理,包含五个生命周期的钩子函数
Vue.directive('color', {
// 绑定的生命周期
// el当前操作的dom元素, binding(传入的数据及属性等),vnode虚拟dom节点
bind(el, binding, vnode) {
console.log('bind');
console.log(el, binding, vnode);
el.style.color = binding.value
},
// 组件更新的时候调用
componentUpdated(el, binding, vnode, oldvnode) {
console.log('componentUpdated');
},
// 插入自定义指令的时候调用
inserted() {
console.log('inserted');
},
// 解绑时调用
unbind() {
console.log('unbind');
},
updated() {
console.log('updated');
},
})

const vm = new Vue({
el: '#app',
data: {
names: '袁同学!',
msg: 'hello',
color: 'pink',
htmlCode:"<h3>你好</h3>"
},
directives:{
/*
指令名:{
钩子函数
}
*/
// placeholder(el,binding,vnode){
// el.setAttribute('placeholder',binding.value)
// },
"placeholder":function(el,binding,vnode){
el.setAttribute('placeholder',binding.value)
},

// 所有钩子全部填入
"myhtml":{
bind(el,binding,vnode){
el.innerHTML = binding.value
},
inserted(el,binding,vnode){

},
update(){

},
componentUpdated(){

},
unbind(){

},
}
}
})
</script>

filter过滤器(vue3已废弃)

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
<div id="app">
<h1>你好 {{names}}</h1>
<!-- 基础使用 -->
{{db | fixed}}<br>
<!-- 支持传参 -->
{{db | fixed(3)}}<br>
<!-- 常用于格式化 -->
<h2>{{ new Date() | format}}</h2>
</div>
<script src="./lib/vue.js"></script>
<script>
Vue.config.productionTip = false

const vm = new Vue({
el: '#app',
data: {
names: '袁同学!',
db: 3.1415926
},
filters: {
// 类似于方法
// 小数点
fixed(data, len = 2) {
return data.toFixed(len)
},
format(date) {
let year = date.getFullYear()
let month = date.getMonth() + 1
let day = date.getDate()
return `${year}-${month}-${day}`
}
}
})
</script>

computed计算属性

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
<div id="app">
<h1>你好 {{names}}</h1>
<input type="text" v-model="number1">+
<input type="text" v-model="number2">=
<input type="text" v-bind:value="sum">
<hr>
{{sum1}}
<button @click="sum1=20">sum1=20</button>
</div>
<script src="./lib/vue.js"></script>
<script>
Vue.config.productionTip = false

const vm = new Vue({
el: '#app',
data: {
names: '袁同学!',
number1:'',
number2:'',
number3:0,
},
computed:{
// 基础版本
sum(){
return Number(this.number1) + Number(this.number2)
},
// 完整版本
sum1:{
get(){
console.log('get');
return this.number3
},
set(v){
console.log('set');
this.number3 = v
}
}
}
})
</script>

computed和methods的区别(面试题)

  • computed会缓存数据,只有当数据变化了才会重新编译
  • methods每次调用都会重新编译
  • computed的效率高于methods

watch监听器

用于监听劫持的数据变化的

三个属性

  • handler 处理函数
  • deep 是否深度监听
  • immediate 是否开始就监听
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
<div id="app">
<h1>你好 {{names}}</h1>
{{number}}<button @click="number=2">改变number</button>
{{number2}}<button @click="number2=2">改变number2</button>
{{user}}<button @click="user.username='tom'">改变user.username</button>
</div>
<script src="./lib/vue.js"></script>
<script>
Vue.config.productionTip = false

const vm = new Vue({
el: '#app',
data: {
names: '袁同学!',
number: 1,
number2: 1,
user:{
username:'jerrry'
}
},
watch: {
// 默认是用的是handler ,deep和immediate默认为false
// handler有两个参数newValue oldValue
number(newValue, oldValue) {
console.log(newValue, oldValue);
newValue = oldValue + 10
},
//
number:{
handler(newValue, oldValue){
console.log('number监听了');
},
deep:true,
immediate:true
},
"user":{
handler(newValue, oldValue){
console.log('user监听了');
},
deep:true,
immediate:true
}
}
})
</script>

computed和watch的区别(面试题)

  • computed有缓存,不支持异步操作
  • watch没有缓存,支持异步操作
  • computed 有get和set属性
  • watch 有handler、deep、immediate