Vue的响应式系统是通过拦截数组变异方法来实现对数组的响应式追踪的,因此,如果你使用了变异方法如push、pop、splice等来改变数组,watch将无法触发,因为并没有产生新的数组,只是对已有的数组进行了操作。
解决方法是使用非变异方法,如concat、slice、map等来返回一个新的数组,从而使watch可以触发,例如:
<template>
<div>{{userInfo.name}}</div>
</template>
<script>
import { mapState } from 'vuex'
export default {
computed: {
...mapState(['user'])
},
watch: {
"user.friends": function (newVal, oldVal) {
console.log('friends changed')
}
},
created() {
const newFriends = this.user.friends.slice()
this.$store.commit('updateFriends', newFriends)
}
}
</script>
在这个例子中,我们将user.friends通过slice方法复制一份新数组,然后让updateFriends方法使用newFriends来更新Vuex中的user.friends,这样就能让watch捕获到对象的变化了。
2. 对象的属性添加不能触发watch。
如果在watch中监听对象属性的变化,但是对象的属性发生改变时,watch不会触发更新,原因是这个属性没有被添加为响应式属性。
解决方法是使用Vue.set方法,将要监听的属性添加为响应式属性,例如:
<template>
<div>{{userInfo.name}}</div>
</template>
<script>
import Vue from 'vue'
import { mapState } from 'vuex'
export default {
computed: {
...mapState(['user'])
},
watch: {
"userInfo.name": function (newVal, oldVal) {
console.log('name changed')
}
},
created() {
Vue.set(this.user, 'userInfo', { name: 'Alice' })
}
}
</script>
在这个例子中,我们使用Vue.set方法来将userInfo添加为响应式属性,并初始化一个name属性,这样就能监听到对象属性的变化了。