我在vue-router中发现了一个问题,它引发了我很多。 总是当我在我的路线之间切换时,会创建一个新的组件实例。此外,旧实例不会被删除,而是在后台运行!
我希望当我打开路线时,旧组件将被销毁或停止运行。
是否有解决该问题的解决方法?
这是一个小提琴:https://jsfiddle.net/4xfa2f19/5885/
let foo = {
template: '<div>Foo</div>',
mounted() {
console.log('Mount Foo with uid: ' + this._uid);
setInterval(() => {console.log('Instance ' + this._uid + ' of Foo is running')}, 500);
}
};
let bar = {
template: '<div>Bar</div>',
mounted() {
console.log('Mount Bar with uid: ' + this._uid);
setInterval(() => {console.log('Instance ' + this._uid + ' of Bar is running')}, 500);
}
};
const router = new VueRouter({
routes: [
{ path: '/user/foo', component: foo },
{ path: '/user/bar', component: bar }
]
});
const app = new Vue({ router }).$mount('#app');
答案 0 :(得分:6)
有两种方法可以解决这个问题:
destroy
挂钩如果您使用任何外部事件监听器,例如setInterval
,addEventListener
等,则当组件被销毁时,您还需要取消注册,例如:
{
name: '...',
template: '...',
data() {
return {
interval: undefined,
timeout: undefined
};
},
mounted() {
interval = setInterval(() => {console.log('Instance ' + this._uid + ' of myself is running')}, 500);
timeout = setTimeout(() => {console.log('Instance ' + this._uid + ' of myself is running')}, 500);
document.addEventListener('click', this.onOutsideClick);
},
beforeDestroy() {
// Cleanup interval
clearInterval(interval);
// Cleanup any pending timeouts
clearTimeout(timeout);
// Cleanup any event listeners outside the root of the element
document.removeEventListener('click', this.onOutsideClick);
},
methods: {
onOutsideClick() {
...
}
}
}
当使用keepalive时,Vue会缓存你的组件,并在后台保持它活着,这意味着只有一个实例存在。如果您有大量路径,这可能会消耗更多内存
<keep-alive>
<router-view></router-view>
</keep-alive>
答案 1 :(得分:2)
总是当我在我的路线之间切换时,会创建一个新的组件实例。
这是预料之中的。你可以保持instanes活着并使用<keep-alive>
组件重新使用它们,但这通常不是必需的,如果是这样,需要特别注意重新启动necesseray中所有重用组件的本地状态。
创建一个新实例更加清晰,因此是默认行为。
此外,旧实例不会被删除,而是在后台运行!
没想到。以前的实例都被销毁了。
setInterval(() => {console.log('Instance ' + this._uid + ' of Foo is running')}, 500);
好吧,因为这个intervall回调包含对组件实例的引用,所以它不能被浏览器垃圾收集,所以你让它们保持活着,而不是Vue。
如果没有这个intervall,我会在路由器销毁它们之后期望垃圾收集。
答案 2 :(得分:0)
同一问题在这里指出:https://github.com/vuejs/vuex/issues/1580
作为解决方法,您可以使用过渡模式输出。罗兰达(Rolandoda)
<transition mode="out-in"> <router-view></router-view> </transition>
答案 3 :(得分:0)
在 Vue 3 中,语法发生了变化。告诉 Vue Router 让所有组件保持活动状态的解决方案是:
<router-view v-slot="{ Component }">
<keep-alive>
<component :is="Component" />
</keep-alive>
</router-view>
如果你只想让某个人活着,那么你可以使用这个:
<router-view v-slot="{ Component }">
<keep-alive include="foo">
<component :is="Component" />
</keep-alive>
</router-view>
或者确保没有一个人活着(但所有其他人都活着),这样做:
<router-view v-slot="{ Component }">
<keep-alive exclude="foo">
<component :is="Component" />
</keep-alive>
</router-view>