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

3.1 KiB
Raw Permalink Blame History

title date tags categories
Vue 侦听对象中的属性 2021-05-08 17:52:33
前端
Vue
前端

Vue 提供了一个 watch 方法可以让使用者去监听某些 data 内的数据变动,触发相应的方法,比如:

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 的值发送请求动态获取:

export default {
  data() {
    return {
      max: 0,
      queryData: {
        date: '2021-05-08',
        count: 0,
        // 其它属性...
      }
    }
  },
  // ...
  methods: {
    getMax(date) {
      // 发送请求后根据响应的值修改 this.max 的值
    }
  }
}

这时,我们如果只侦听 queryDataqueryData.date 更改时并不会触发侦听器,因为我们并没有给 queryData 重新赋值。

很多人都表示可以设置侦听器的 deep 选项为 true,说实话,如果只是侦听 date 属性的话,我并不推荐这种方法,因为这样不仅 date 属性更改时会执行侦听器中的方法,其它属性(比如 count)的值改变了,也会执行侦听器中的方法,还需要在其中加入判断,就很不理想。我推荐的方式是,将计算属性监听器结合起来使用,如下:

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 的官方文档:

其实使用组合式 API的话2.x 和 3.x 在这里并没有什么区别Vue 3.x 中在 setup 里面使用的话,思路也是一样,只是形式不同。