侦听组件实例上的响应式 property 或函数计算结果的变化。回调函数得到的参数为新值和旧值。我们只能将顶层的 data
、prop
或 computed
property 名作为字符串传递。对于更复杂的表达式,用一个函数取代。
假设 data
定义的数据如下:
data() {
return {
a: 1,
b: 2,
c: {
d: 3,
e: 4
}
}
},
单个的顶层属性,第一个参数是字符串,第二个参数是函数。
created() {
// 顶层属性
this.$watch('a', (newVal, oldVal) => {
// 做点什么
})
}
包含嵌套的对象里面的属性,两个参数都必须是函数形式。
created() {
// 用于监视单个嵌套属性
this.$watch(
() => this.c.d,
(newVal, oldVal) => {
// 做点什么
}
)
}
如果使用的是 vue3 请使用上面的写法,如果使用的是 vue2 可以使用简单的键路径。
created() {
// 键路径
this.$watch('c.d', (newVal, oldVal) => {
// 做点什么
})
}
对于更复杂的表达式,用一个函数取代。
created() {
// 用于监视复杂表达式的函数
this.$watch(
// 表达式 `this.a + this.b` 每次得出一个不同的结果时
// 处理函数都会被调用。
// 这就像监听一个未被定义的计算属性
() => this.a + this.b,
(newVal, oldVal) => {
// 做点什么
}
)
}
当侦听的值是一个对象或者数组时,对其属性或元素的任何更改都不会触发侦听器,因为它们引用相同的对象/数组:
const app = Vue.createApp({
data() {
return {
article: {
text: 'Vue is awesome!'
},
comments: ['Indeed!', 'I agree']
}
},
created() {
this.$watch('article', () => {
console.log('Article changed!')
})
this.$watch('comments', () => {
console.log('Comments changed!')
})
},
methods: {
// 这些方法不会触发侦听器,因为我们只更改了Object/Array的一个property,
// 不是对象/数组本身
changeArticleText() {
this.article.text = 'Vue 3 is awesome'
},
addComment() {
this.comments.push('New comment')
},
// 这些方法将触发侦听器,因为我们完全替换了对象/数组
changeWholeArticle() {
this.article = { text: 'Vue 3 is awesome' }
},
clearComments() {
this.comments = []
}
}
})
为了发现对象内部值的变化,可以在选项参数中指定 deep: true
。在选项参数中指定 immediate: true
将立即以表达式的当前值触发回调:
created() {
// 顶层属性
this.$watch('c', (newVal, oldVal) => {
// 做点什么
}, { deep: true, immediate: true })
}
// this.c.d = '6'
// this.c.e = '7'
注意:在变更 (不是替换) 对象或数组时,旧值将与新值相同,因为它们的引用指向同一个对象/数组。Vue 不会保留变更之前值的副本。
$watch
返回一个取消侦听函数,用来停止触发回调。
命令式的 $watch
API,和 options API 中的 watch 选项类似,但是和 composition API 的 watch 还是有点区别的。因为后者可以使用数组来同时侦听多个源:
watch([fooRef, barRef], ([foo, bar], [prevFoo, prevBar]) => {
/* ... */
})
需要在数据变化时执行异步或开销较大的操作时,请使用 watch 处理。