vue-router 总是创建一个新的 Component 实例
Posted
技术标签:
【中文标题】vue-router 总是创建一个新的 Component 实例【英文标题】:vue-router creates always a new Component instance 【发布时间】:2018-08-31 15:29:54 【问题描述】:我在 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');
【问题讨论】:
Update VueJs component on route change的可能重复 【参考方案1】:有两种方法可以解决这个问题:
在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()
...
使用 keep-alive 使组件保持活动状态
当使用 keepalive 时,Vue 会缓存你的组件,并在后台保持它处于活动状态,这意味着永远只会存在一个实例。如果您有大量路线,这可能会消耗更多内存
<keep-alive>
<router-view></router-view>
</keep-alive>
【讨论】:
【参考方案2】:当我在我的路由之间切换时,总是会创建一个新的组件实例。
这是意料之中的。您可以通过<keep-alive>
组件保持实例处于活动状态并重新使用它们,但这通常不是必需的,如果是这样,需要特别注意重新启动所有需要的重用组件的本地状态。
创建一个新实例更加简洁,因此是默认行为。
此外,旧实例不会被删除,而是在后台运行!
这不是预期的。先前的实例被销毁。
setInterval(() => console.log('Instance ' + this._uid + ' of Foo is running'), 500);
好吧,由于这个间隔回调包含对组件实例的引用,它不能被浏览器垃圾收集,所以你要让它们保持活动状态,而不是 Vue。
如果没有那个间隔,我希望实例在路由器销毁它们后被垃圾收集。
【讨论】:
谢谢。有没有办法检查是否触发了“破坏”,以便我可以清除间隔? 只需使用 Vue 的生命周期钩子即可。你已经知道mounted,所以你也知道beforeDestroy
? vuejs.org/v2/api/#beforeDestroy【参考方案3】:
这里说明了同样的问题:https://github.com/vuejs/vuex/issues/1580
作为一种解决方法,您可以使用过渡模式 out-in。罗兰达
<transition mode="out-in"> <router-view></router-view> </transition>
【讨论】:
【参考方案4】:在 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>
【讨论】:
以上是关于vue-router 总是创建一个新的 Component 实例的主要内容,如果未能解决你的问题,请参考以下文章
vue-router组件里面点击一个按钮跳转到一个新的组件该怎么实现
vue动态添加路由,跳转页面时,页面报错路由重复:vue-router.esm.js?8c4f:16 [vue-router] Duplicate named routes definition: {
vue动态添加路由,跳转页面时,页面报错路由重复:vue-router.esm.js?8c4f:16 [vue-router] Duplicate named routes definition: {