[英]vue-router creates always a new Component instance
我在 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');
有兩種方法可以解決這個問題:
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>
當我在路由之間切換時,總是會創建一個新的組件實例。
這是預期的。 您可以使實例保持活動狀態並通過<keep-alive>
組件重新使用它們,但這通常不是必需的,如果是這樣,則需要特別注意重新啟動所有需要重新使用的組件的本地狀態。
創建新實例要干凈得多,因此是默認行為。
此外,舊實例不會被刪除並在后台運行!
這不是預期的。 先前的實例被銷毀。
setInterval(() => {console.log('Instance ' + this._uid + ' of Foo is running')}, 500);
好吧,由於此間隔回調包含對組件實例的引用,因此瀏覽器無法對其進行垃圾回收,因此您要使它們保持活動狀態,而不是 Vue。
如果沒有那個間隔,我希望實例在路由器銷毀它們后被垃圾收集。
這里陳述了同樣的問題: https : //github.com/vuejs/vuex/issues/1580
作為一種解決方法,您可以使用外向轉換模式。 羅蘭多達
<transition mode="out-in"> <router-view></router-view> </transition>
在 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>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.