Vue watch 意外调用了两次
Vue watch unexpectedly called twice
udpate #2: 这不是错误,是我自己的错。我通过 extend()
方法扩展了 BaseComponent
并将 extends: BaseComponent
放入选项中。我以为我需要两者,但选项中的 extends: BaseComponent
似乎就足够了。
所以双 "extend" 显然复制了观察者,这导致了我在问题中记录的奇怪行为。
更新: 我发现了导致这个问题的原因:观察者似乎是重复的,因为它在 BaseComponent
中,由 Component
在我的示例中使用。
所以 export default BaseComponent.extend({ name: 'Component', ...})
似乎复制了 watch
对象而不是 "merging" 它 - 现在 BaseComponent
中有一个(最初实现的地方)和 [=18 中有一个=] - 当然,两者都会对道具更新做出反应。
恕我直言,这似乎是一个错误。
对单个文件组件使用 vue-cli
。
我正在通过一种方法在一个组件中设置一个道具:
<template>
<div>
<other-component :my-object="myObject" />
</div>
</template>
<script>
export default (Vue as VueConstructor).extend({
data() {
return {
myObject: null
}
},
methods: {
actionButtonClicked(action, ID) {
console.log('actionButtonClicked');
this.myObject = {
action: action,
ID: ID
}
}
}
});
</script>
然后我用观察者观察另一个组件中的道具 - 但每次执行该方法时都会调用两次。
<script>
export default (Vue as VueConstructor<Vue>).extend({
/* ... */
props: {
myObject: {
type: Object,
default: null
},
watch: {
'myObject.ID'(value, oldValue) {
console.log('watcher executed');
}
}
/* ... */
});
</script>
所以在控制台中我得到输出:
actionButtonClicked
watcher executed
watcher executed
.. 每次调用该方法时。
我已经尝试了所有不同的观察者变体 - 例如 deep: true
+ handler
。但这一切都没有改变 watcher 被调用两次的情况。
我的观察者被复制了,因为我用两种方式扩展了我的 BaseComponent
:
- 通过组件本身的
extend()
方法
- 通过将
extends: BaseComponent
放入 "outer" 组件的选项中
我认为您需要使用这两段代码来扩展另一个组件,但显然这是错误的并且会导致不良的副作用。
在我的例子中,我在一个组件中有 "watch" 并在页面上使用了该组件两次,因此 "watch" 被注册了两次。
希望对遇到同样问题的人有所帮助。
您可能想使用 vue 控制台等工具检查组件树,或者手动按照页面上的导入组件列表进行操作,以确保没有组件被无意中导入两次。
我在默认布局中有一个模态,但想在特定页面上显示模态 body/main 内容(即不在模态中触发)。我最终导入了两者,并且 vue 正确地将它们视为单独的实例。这意味着奇怪的行为,比如点击两次模态框消失,当然,他们的观察者被调用两次
udpate #2: 这不是错误,是我自己的错。我通过 extend()
方法扩展了 BaseComponent
并将 extends: BaseComponent
放入选项中。我以为我需要两者,但选项中的 extends: BaseComponent
似乎就足够了。
所以双 "extend" 显然复制了观察者,这导致了我在问题中记录的奇怪行为。
更新: 我发现了导致这个问题的原因:观察者似乎是重复的,因为它在 BaseComponent
中,由 Component
在我的示例中使用。
所以 export default BaseComponent.extend({ name: 'Component', ...})
似乎复制了 watch
对象而不是 "merging" 它 - 现在 BaseComponent
中有一个(最初实现的地方)和 [=18 中有一个=] - 当然,两者都会对道具更新做出反应。
恕我直言,这似乎是一个错误。
对单个文件组件使用 vue-cli
。
我正在通过一种方法在一个组件中设置一个道具:
<template>
<div>
<other-component :my-object="myObject" />
</div>
</template>
<script>
export default (Vue as VueConstructor).extend({
data() {
return {
myObject: null
}
},
methods: {
actionButtonClicked(action, ID) {
console.log('actionButtonClicked');
this.myObject = {
action: action,
ID: ID
}
}
}
});
</script>
然后我用观察者观察另一个组件中的道具 - 但每次执行该方法时都会调用两次。
<script>
export default (Vue as VueConstructor<Vue>).extend({
/* ... */
props: {
myObject: {
type: Object,
default: null
},
watch: {
'myObject.ID'(value, oldValue) {
console.log('watcher executed');
}
}
/* ... */
});
</script>
所以在控制台中我得到输出:
actionButtonClicked
watcher executed
watcher executed
.. 每次调用该方法时。
我已经尝试了所有不同的观察者变体 - 例如 deep: true
+ handler
。但这一切都没有改变 watcher 被调用两次的情况。
我的观察者被复制了,因为我用两种方式扩展了我的 BaseComponent
:
- 通过组件本身的
extend()
方法 - 通过将
extends: BaseComponent
放入 "outer" 组件的选项中
我认为您需要使用这两段代码来扩展另一个组件,但显然这是错误的并且会导致不良的副作用。
在我的例子中,我在一个组件中有 "watch" 并在页面上使用了该组件两次,因此 "watch" 被注册了两次。
希望对遇到同样问题的人有所帮助。
您可能想使用 vue 控制台等工具检查组件树,或者手动按照页面上的导入组件列表进行操作,以确保没有组件被无意中导入两次。
我在默认布局中有一个模态,但想在特定页面上显示模态 body/main 内容(即不在模态中触发)。我最终导入了两者,并且 vue 正确地将它们视为单独的实例。这意味着奇怪的行为,比如点击两次模态框消失,当然,他们的观察者被调用两次