Watch侦听器

watch侦听器允许开发者监视数据的变化,从而对数据的变化做出特定的操作

所有的侦听器,都应该被定义到 watch 节点下,侦听器本质上是一个函数

一个常用的场景是输入用户名后发送ajax请求判断用户名是否重复,下面的案例在控制台看代码输出

方法格式的侦听器

要监视哪个数据的变化,就把数据名作为方法名

侦听器接受两个参数,旧的数据值和新的数据值,其中新的数据值是第一个参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<div id="app">
<input type="text" v-model="username">
</div>
<script>
const vm = new Vue({
el: '#app',
data: {
username: 'admin'
},
// 所有的侦听器,都应该被定义到 watch 节点下
watch: {
// 侦听器本质上是一个函数,要监视哪个数据的变化,就把数据名作为方法名即可
// 新值在前,旧值在后
username(newVal) {
if (newVal === '') return
// 1. 调用 jQuery 中的 Ajax 发起请求,判断 newVal 是否被占用!!!
$.get('https://www.escook.cn/api/finduser/' + newVal, function (result) {
console.log(result)
})
}
}
})
</script>

方法格式的侦听器无法在刚进入页面的时候就自动触发,并且当data是对象格式的数据时,监听数据对象本身无法监听到对象属性的变化

对象格式的侦听器

进入页面就触发

handler 作为对象格式侦听器的处理函数,同样接受两个参数

通过控制对象的 immediate 属性来控制侦听器是否自动触发一次

immediate 属性的默认值是 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
<div id="app">
<input type="text" v-model="username">
</div>
<script>
const vm = new Vue({
el: '#app',
data: {
username: 'admin'
},
// 所有的侦听器,都应该被定义到 watch 节点下
watch: {
// 定义对象格式的侦听器
username: {
// 侦听器的处理函数
handler(newVal, oldVal) {
console.log(newVal, oldVal)
},
// immediate 选项的默认值是 false
// immediate 的作用是:控制侦听器是否自动触发一次!
immediate: true
}
}
})
</script>

深度侦听器对象格式的数据

当我们的数据 data 是一个对象的时候,我们需要监听的是对象的属性变化,通过对象格式监听器的 deep 属性来控制对 对象形式数据 属性的深度监听

只要数据对象中任何一个属性变化了,就会触发对对象的侦听器

这样的写法每次需要操作还需要在方法内部使用 . 来访问对象属性

如果我们想直接侦听对象中的属性,我们可以直接写一个表达式

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">
<input type="text" v-model="info.username">
<input type="text" v-model="info.address.city">
</div>
<script>
const vm = new Vue({
el: '#app',
data: {
// 用户的信息对象
info: {
username: 'admin',
address: {
city: '北京'
}
}
},
// 所有的侦听器,都应该被定义到 watch 节点下
watch: {
info: {
handler(newVal) {
console.log(newVal.address.city)
// console.log(newVal.username)
},
// 开启深度监听,只要对象中任何一个属性变化了,都会触发“对象的侦听器”
deep: true
},
// 如果要侦听的是对象的子属性的变化,则必须包裹一层单引号
// 函数格式
// 'info.username'(newVal) {
// console.log(newVal)
// }
// 对象格式
'info.username':{
handler(newVal){
console.log(newVal)
}
}
}
})
</script>

计算属性

计算属性就是指通过一些系列计算后,最终得到一个属性值,这个动态计算出来的属性值可以被模板结构或 methodes 方法使用

比如实现修改rgb的值让盒子的背景色达到自动变色的效果

当不使用计算属性时,我们对于backgroundcolor属性需要每次动态计算我们对 style 绑定的就是一个{ }样式对象,每次使用模板字符串动态计算其值,把计算结果给 style 属性,注意在vue中 v-bind 还有插值语法中可以写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
37
<div id="app">
<div>
<span>R:</span>
<input type="text" v-model.number="r">
</div>
<div>
<span>G:</span>
<input type="text" v-model.number="g">
</div>
<div>
<span>B:</span>
<input type="text" v-model.number="b">
</div>
<hr>
<!-- 专门用户呈现颜色的 div 盒子 -->
<!-- 在属性身上,: 代表 v-bind: 属性绑定 -->
<!-- :style 代表动态绑定一个样式对象,它的值是一个 { } 样式对象 -->
<div class="box" :style="{ backgroundColor: `rgb(${r}, ${g}, ${b})` }">
{{ `rgb(${r}, ${g}, ${b})` }}
</div>
<button @click="show">按钮</button>
</div>
<script>
var vm = new Vue({
el: '#app',
data: {
// 红色 绿色 蓝色
r: 0, g: 0, b: 0
},
methods: {
// 点击按钮,在终端显示最新的颜色
show() {
console.log(`rgb(${this.r}, ${this.g}, ${this.b})`)
}
},
});
</script>
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
  <div id="app">
<div>
<span>R:</span>
<input type="text" v-model.number="r">
</div>
<div>
<span>G:</span>
<input type="text" v-model.number="g">
</div>
<div>
<span>B:</span>
<input type="text" v-model.number="b">
</div>
<hr>
<!-- :style 代表动态绑定一个样式对象,它的值是一个 { } 样式对象 -->
<!-- 当前的样式对象中,只包含 backgroundColor 背景颜色 -->
<div class="box" :style="{ backgroundColor: rgb }">
{{ rgb }}
</div>
<button @click="show">按钮</button>
</div>
<script>
var vm = new Vue({
el: '#app',
data: {
// 红色 绿色 蓝色
r: 0, g: 0, b: 0
},
methods: {
// 点击按钮,在终端显示最新的颜色
show() {
console.log(this.rgb)
}
},
// 所有的计算属性,都要定义到 computed 节点之下
// 计算属性在定义的时候,要定义成“方法格式”
computed: {
// rgb 作为一个计算属性,被定义成了方法格式,
// 最终,在这个方法中,要返回一个生成好的 rgb(x,x,x) 的字符串
rgb() {
return `rgb(${this.r}, ${this.g}, ${this.b})`
}
}
});
// 在控制台看打印出来的vue对象
console.log(vm)
</script>

特点:

  1. 定义的时候,要被定义为“方法”
  2. 在使用计算属性的时候,当普通的属性使用即可,就类似于该vue对象多了一个叫 rgb 的数据

好处:

  1. 实现了代码的复用
  2. 只要计算属性中依赖的数据源变化了,则计算属性会自动重新求值

axios

axios 是一个专注于网络请求的库!

axios传送门

1
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>

一般我们在vue中使用 axios 时都会使用下面的命令来安装

1
npm install axios -S

并且使用前通过 import axios from 'axios' 来导入

axios的GET请求

直接使用 axios 发送 Get 请求 在控制台查看输出

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script>
// http://www.liulongbin.top:3006/api/getbooks
// 1. 调用 axios 方法得到的返回值是 Promise 对象
axios({
// 请求方式
method: 'GET',
// 请求的地址
url: 'http://www.liulongbin.top:3006/api/getbooks',
// GET 请求参数
params: {
id: 1
}
}).then(function (result) {
console.log(result)
})
</script>

axios的POST请求

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<button id="btnPost">发起POST请求</button>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script>
document.querySelector('#btnPost').addEventListener('click', function () {
axios({
method: 'POST',
url: 'http://www.liulongbin.top:3006/api/post',
data: {
name: 'zs',
age: 20
}
}).then(function(result){
console.log(result)
})
})
</script>

axios 配合 async 和 await 使用

对于Es7asyncawait 可以看 Promise 、async、await 的学习

在下面的例子中,通过 async/await 和 解构赋值 来使 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
<button id="btnPost">发起POST请求</button>
<button id="btnGet">发起GET请求</button>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script>
document.querySelector('#btnPost').addEventListener('click', async function () {
// 如果调用某个方法的返回值是 Promise 实例,则前面可以添加 await
// await 只能用在被 async “修饰”的方法中
const { data } = await axios({
method: 'POST',
url: 'http://www.liulongbin.top:3006/api/post',
data: {
name: 'zs',
age: 20
}
})
console.log(data)
})
document.querySelector('#btnGet').addEventListener('click', async function () {
// 解构赋值的时候,使用 : 进行重命名
// 1. 调用 axios 之后,使用 async/await 进行简化
// 2. 使用解构赋值,从 axios 封装的大对象中,把 data 属性解构出来
// 3. 把解构出来的 data 属性,使用 冒号 进行重命名,一般都重命名为 { data: res }
const { data: res } = await axios({
method: 'GET',
url: 'http://www.liulongbin.top:3006/api/getbooks'
})
console.log(res.data)
})
</script>

我们还可以直接通过 axios.get()axios.post() 来进行 get 和 post 请求的发送

1
2
3
axios.get('http://www.liulongbin.top:3006/api/getbooks', {
params: { id: 1 }
})
1
axios.post('http://www.liulongbin.top:3006/api/post', { name: 'zs', gender: '女' })

axios挂载在vue原型下

不论是通过import axios from 'axios' 还是通过 <script src="https://unpkg.com/axios/dist/axios.min.js"></script> 每个组件都需要单独引入并且使用,这样太麻烦了

我们可以在 main.js 中导入 axios 并且挂载在vue原型中,并且在挂载前设置请求根路径,这样我们就使用或修改服务器地址后进行维护都比较方便

1
2
3
4
5
6
import Vue from 'vue'
import App from './App.vue'
import axios from 'axios'

axios.defaults.baseURL='请求根路径'
Vue.prototype.$http = axios

在这之后我们在每个组件中使用时,只需要通过 this.$http 就可以使用了,这里 $http 是一个习惯,也可以写成别的名字