blog/Vue-侦听对象中的属性.md

116 lines
3.1 KiB
Markdown
Raw Permalink Normal View History

2023-01-04 13:49:09 +08:00
---
title: Vue 侦听对象中的属性
date: 2021-05-08 17:52:33
tags:
- 前端
- Vue
categories:
- 前端
---
Vue 提供了一个 watch 方法可以让使用者去监听某些 data 内的数据变动,触发相应的方法,比如:
```javascript
export default {
data() {
return {
question: '',
answer: 'Questions usually contain a question mark. ;-)'
}
},
watch: {
// whenever question changes, this function will run
question(newQuestion, oldQuestion) {
if (newQuestion.indexOf('?') > -1) {
this.getAnswer()
}
}
},
methods: {
getAnswer() {
this.answer = 'Thinking...'
axios
.get('https://yesno.wtf/api')
.then(response => {
this.answer = response.data.answer
})
.catch(error => {
this.answer = 'Error! Could not reach the API. ' + error
})
}
}
}
```
但是,当我们要侦听的数据是某个对象中的属性怎么办?
以前几天我所遇到的需求为例,一个对话框中的表单绑定了 `queryData`,其中 `date` 绑定了一个日期选择器,`count` 则绑定了一个计数器,`max` 则是该计数器的值,需要根据 `date` 的值发送请求动态获取:
```javascript
export default {
data() {
return {
max: 0,
queryData: {
date: '2021-05-08',
count: 0,
// 其它属性...
}
}
},
// ...
methods: {
getMax(date) {
// 发送请求后根据响应的值修改 this.max 的值
}
}
}
```
这时,我们如果只侦听 `queryData``queryData.date` 更改时并不会触发侦听器,因为我们并没有给 `queryData` 重新赋值。
很多人都表示可以设置侦听器的 `deep` 选项为 `true`,说实话,如果只是侦听 `date` 属性的话,我并不推荐这种方法,因为这样不仅 `date` 属性更改时会执行侦听器中的方法,其它属性(比如 `count`)的值改变了,也会执行侦听器中的方法,还需要在其中加入判断,就很不理想。我推荐的方式是,将**计算属性**和**监听器**结合起来使用,如下:
```javascript
export default {
data() {
return {
max: 0,
queryData: {
date: '2021-05-08',
count: 0,
// 其它属性...
}
}
},
computed: {
_queryData_date() {
return this.queryData.date
}
},
watch: {
_queryData_date(oldDate, newDate) {
this.getMax(newDate)
}
},
methods: {
getMax(date) {
// 发送请求后根据响应的值修改 this.max 的值
}
}
}
```
这样,我们就只侦听了 `queryData.date` 的值,可以在它改变时执行 `getMax` 方法。
> 关于计算属性和侦听器的使用方法,请查看 Vue 的官方文档:
>
> - Vue 2.x
> https://cn.vuejs.org/v2/guide/computed.html
> https://cn.vuejs.org/v2/guide/reactivity.html
> - Vue 3.x
> https://v3.cn.vuejs.org/guide/computed.html
> https://v3.cn.vuejs.org/guide/reactivity-computed-watchers.html
>
> ***其实使用组合式 API的话2.x 和 3.x 在这里并没有什么区别Vue 3.x 中在 setup 里面使用的话,思路也是一样,只是形式不同。***