Vue-侦听器

基本示例

export default {
  data() {
    return {
      question: '',
      answer: 'Questions usually contain a question mark. ;-)'
    }
  },
  watch: {
    // 每当 question 改变时,这个函数就会执行
    question(newQuestion, oldQuestion) {
      if (newQuestion.includes('?')) {
        this.getAnswer()
      }
    }
  },
  methods: {
    async getAnswer() {
      this.answer = 'Thinking...'
      try {
        const res = await fetch('https://yesno.wtf/api')
        this.answer = (await res.json()).answer
      } catch (error) {
        this.answer = 'Error! Could not reach the API. ' + error
      }
    }
  }
}
<p>
  Ask a yes/no question:
  <input v-model="question" />
</p>
<p>{{ answer }}</p>

深度侦听器

watch默认是浅层的:被侦听的属性,仅在被赋新值时,才会触发回调函数——而嵌套属性的变化不会处罚。如果想侦听所有嵌套的变更,你需要深层侦听器:

export default {
  watch: {
    someObject: {
      handler(newValue, oldValue) {
        // 注意:在嵌套的变更中,
        // 只要没有替换对象本身,
        // 那么这里的 `newValue` 和 `oldValue` 相同
      },
      deep: true
    }
  }
}

即时回调的侦听器

watch默认是懒执行的:仅当数据源变化时,才会执行回调。但在某些场景中,我们希望在创建侦听器时,立即执行一遍回调。举例,我们想请求一些初始数据,然后在相关状态更改时重新请求数据。

我们可以用一个对象来声明侦听器,这个对象有handler方法和immediate:true选项,这样便能强制回调函数立即执行。

export default {
  // ...
  watch: {
    question: {
      handler(newQuestion) {
        // 在组件实例创建时会立即调用
      },
      // 强制立即执行回调
      immediate: true
    }
  }
  // ...
}

回调函数的初次执行就发生在created钩子之前。Vue此时已经处理了data、computed和methods选项,所以这些属性在第一次调用时就是可用的。

回调的处罚世纪

当你更改响应式状态,它可能会同时出发Vue组件更新和侦听器回调。

默认情况下,用户创建的侦听器回调,都会在Vue组件更新之前被调用。这意味着你在侦听器回调中访问的DOM将时被Vue更新之前的状态。

如果想在侦听器回调中能访问被Vue更新之后的DOM,你需要指明flush:‘post‘选项:

export default {
  // ...
  watch: {
    key: {
      handler() {},
      flush: 'post'
    }
  }
}