簡體   English   中英

vue-router 總是創建一個新的 Component 實例

[英]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鈎子中正確清理

如果您使用任何外部事件偵聽器,例如setIntervaladdEventListener等,您還需要在組件被銷毀時取消注冊它們,例如:

{
    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>

當我在路由之間切換時,總是會創建一個新的組件實例。

這是預期的。 您可以使實例保持活動狀態並通過<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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM