【发布时间】:2021-11-14 05:56:34
【问题描述】:
关于 Vue 2 的一个问题,我已经没有什么想法了,这会导致手表触发,据我所知,它不应该触发。当我长时间轮询 API 并使用新的、可能更改的数据更新数据时,就会发生这种情况。我希望手表在数据更改时触发,但显然不是在没有数据更改的情况下。
让我把它浓缩为代码的关键部分。这是数据:
data() {
return {
ffGameState: {
errors: {
team1: [false, false, false]
}
}
}
}
这是手表:
watch: {
"ffGameState.errors.team1": {
deep: true,
handler: function(val, oldVal) {
console.log("change detected")
console.log(val)
console.log(oldVal)
}
}
}
最后是检索数据并更新 ffGameState 对象的方法(它在创建时触发):
loadFfGameState() {
var vm = this
this.$http
.get("/gamestates/ff")
.then(response => {
vm.ffGameState = response.data
})
.then(() => {
setTimeout(() => this.loadFfGameState(), 100)
})
}
所有这些都会导致每次获取数据时(即每 100 毫秒)都会触发手表,请查看浏览器的日志输出:
change detected
AudienceScreen.vue?57f6:272 (3) [true, true, true, __ob__: Observer]
AudienceScreen.vue?57f6:273 (3) [true, true, true, __ob__: Observer]
第一眼我能看出的唯一区别是 __ob__.dep.id 发生了变化,但我不认为这会导致手表触发。
我尝试过的事情:
- 直接使用
this,而不是定义var vm = this - 使用
vm.$set(vm, "ffGameState", response.data)
另一个可能有用的信息是 lodash 的 _.isEqual(val, oldVal) 返回 true。
感谢您的帮助,非常感谢!
【问题讨论】:
-
这是正确的行为。
watch会在被监视对象设置 为新实例时触发。loadFfGameState()将ffGameState设置为一个全新的实例,这会触发深度观察器,因为子属性数组是新的。如果在这种情况下需要防止对相同的值发生动作,则需要手动进行比较。 -
谢谢。但不知何故,它似乎没有用 - 这是否意味着只能观察简单的对象类型?那么
deep: true选项有什么作用呢?可能我错过了什么。 -
抱歉发了两次帖子,但我想我明白了。因此,只要其中一个字段更改,例如通过
this.ffGameState.errors.team1 = [true, true, true]为其分配一个新值,它将触发手表。但如果整个对象被替换,则不会。这种理解正确吗?无论如何,非常感谢,我现在只是使用 lodash,它工作得很好。只是认为它应该首先与手表一起使用。 -
@tony19:如果您将此作为正确答案,我可以接受。完成后我将删除此评论。