--- 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 里面使用的话,思路也是一样,只是形式不同。***