Vue keep-alive深刻理解及實踐總結

什麼是 keep-alive

在日常開發中,有部分組件沒有必要屢次初始化,這時,咱們須要將組件進行持久化,使組件的狀態維持不變,在下一次展現時,也不會進行從新初始化組件。html

也就是說,keepaliveVue 內置的一個組件,能夠使被包含的組件保留狀態,或避免從新渲染 。也就是所謂的組件緩存vue

<keep-alive>是Vue的內置組件,能在組件切換過程當中將狀態保留在內存中,防止重複渲染DOM。git

<keep-alive> 包裹動態組件時,會緩存不活動的組件實例,而不是銷燬它們。和 <transition> 類似,<keep-alive> 是一個抽象組件:它自身不會渲染一個 DOM 元素,也不會出如今父組件鏈中。github

prop:正則表達式

  • include: 字符串或正則表達式。只有匹配的組件會被緩存。
  • exclude: 字符串或正則表達式。任何匹配的組件都不會被緩存。

keep-alive的聲明週期執行

  • 頁面第一次進入,鉤子的觸發順序

created-> mounted-> activated
退出時觸發 deactivated 當再次進入(前進或者後退)時,只觸發 activatedvue-router

  • 事件掛載的方法等,只執行一次的放在 mounted 中;組件每次進去執行的方法放在 activated 中;

基本用法

<!--被keepalive包含的組件會被緩存-->
<keep-alive>
    <component><component />
</keep-alive>
複製代碼

keepalive包含的組件不會被再次初始化,也就意味着不會重走生命週期函數
可是有時候是但願咱們緩存的組件能夠可以再次進行渲染,這時 Vue 爲咱們解決了這個問題 被包含在 keep-alive 中建立的組件,會多出兩個生命週期的鉤子: activateddeactivatedsegmentfault

  • activatedkeepalive 包含的組件再次渲染的時候觸發
  • deactivatedkeepalive 包含的組件銷燬的時候觸發

keepalive是一個抽象的組件,緩存的組件不會被 mounted,爲此提供activateddeactivated鉤子函數api

參數理解

keepalive 能夠接收3個屬性作爲參數進行匹配對應的組件進行緩存:數組

  • include 包含的組件(能夠爲字符串,數組,以及正則表達式,只有匹配的組件會被緩存)緩存

  • exclude 排除的組件(覺得字符串,數組,以及正則表達式,任何匹配的組件都不會被緩存)

  • max 緩存組件的最大值(類型爲字符或者數字,能夠控制緩存組件的個數)

注:當使用正則表達式或者數組時,必定要使用 v-bind

<!-- 將(只)緩存組件name爲a或者b的組件, 結合動態組件使用 -->
<keep-alive include="a,b">
  <component></component>
</keep-alive>

<!-- 組件name爲c的組件不緩存(能夠保留它的狀態或避免從新渲染) -->
<keep-alive exclude="c"> 
  <component></component>
</keep-alive>

<!-- 使用正則表達式,需使用v-bind -->
<keep-alive :include="/a|b/">
  <component :is="view"></component>
</keep-alive>

<!-- 動態判斷 -->
<keep-alive :include="includedComponents">
  <router-view></router-view>
</keep-alive>

<!-- 若是同時使用include,exclude,那麼exclude優先於include, 下面的例子只緩存a組件 -->
<keep-alive include="a,b" exclude="b"> 
  <component></component>
</keep-alive>

<!-- 若是緩存的組件超過了max設定的值5,那麼將刪除第一個緩存的組件 -->
<keep-alive exclude="c" max="5"> 
  <component></component>
</keep-alive>
複製代碼

碰見 vue-router 結合router使用,緩存部分頁面

全部路徑下的視圖組件都會被緩存

<keep-alive>
    <router-view>
        <!-- 全部路徑匹配到的視圖組件都會被緩存! -->
    </router-view>
</keep-alive>
複製代碼

若是隻想要router-view裏面的某個組件被緩存,怎麼辦?

  • 使用 include/exclude
  • 使用 meta 屬性

一、用 include (exclude例子相似)

缺點:須要知道組件的 name,項目複雜的時候不是很好的選擇

<keep-alive include="a">
    <router-view>
        <!-- 只有路徑匹配到的 include 爲 a 組件會被緩存 -->
    </router-view>
</keep-alive>
複製代碼

二、使用 meta 屬性

優勢:不須要例舉出須要被緩存組件名稱

使用$route.meta的keepAlive屬性:

<keep-alive>
    <router-view v-if="$route.meta.keepAlive"></router-view>
</keep-alive>
<router-view v-if="!$route.meta.keepAlive"></router-view>
複製代碼

須要在router中設置router的元信息meta:

//...router.js
export default new Router({
  routes: [
    {
      path: '/',
      name: 'Hello',
      component: Hello,
      meta: {
        keepAlive: false // 不須要緩存
      }
    },
    {
      path: '/page1',
      name: 'Page1',
      component: Page1,
      meta: {
        keepAlive: true // 須要被緩存
      }
    }
  ]
})
複製代碼

【加鹽】使用 router.meta 拓展

假設這裏有 3 個路由: A、B、C。

  • 需求:

    • 默認顯示 A
    • B 跳到 A,A 不刷新
    • C 跳到 A,A 刷新
  • 實現方式

    • 在 A 路由裏面設置 meta 屬性:
{
        path: '/',
        name: 'A',
        component: A,
        meta: {
            keepAlive: true // 須要被緩存
        }
}
複製代碼
  • 在 B 組件裏面設置 beforeRouteLeave:
export default {
        data() {
            return {};
        },
        methods: {},
        beforeRouteLeave(to, from, next) {
             // 設置下一個路由的 meta
            to.meta.keepAlive = true;  // 讓 A 緩存,即不刷新
            next();
        }
};
複製代碼
  • 在 C 組件裏面設置 beforeRouteLeave:
export default {
        data() {
            return {};
        },
        methods: {},
        beforeRouteLeave(to, from, next) {
            // 設置下一個路由的 meta
            to.meta.keepAlive = false; // 讓 A 不緩存,即刷新
            next();
        }
};
複製代碼

這樣便能實現 B 回到 A,A 不刷新;而 C 回到 A 則刷新。

防坑指南

1.keep-alive 先匹配被包含組件的 name 字段,若是 name 不可用,則匹配當前組件 components 配置中的註冊名稱。 2.keep-alive 不會在函數式組件中正常工做,由於它們沒有緩存實例。
3.當匹配條件同時在 includeexclude 存在時,以 exclude 優先級最高(當前vue 2.4.2 version)。好比:包含於排除同時匹配到了組件A,那組件A不會被緩存。
4.包含在 keep-alive 中,但符合 exclude ,不會調用 activateddeactivated

實現前進刷新,後退不刷新

感謝 iceuncle 分享的 《vue實現前進刷新,後退不刷新》

總結

路由大法不錯,不須要關心哪一個頁面跳轉過來的,只要 router.go(-1) 就能回去,不須要額外參數。

在非單頁應用的時候,keep-alive 並不能有效的緩存了= =

keep-alive生命週期鉤子函數:activated、deactivated

使用<keep-alive>會將數據保留在內存中,若是要在每次進入頁面的時候獲取最新的數據,須要在activated階段獲取數據,承擔原來created鉤子中獲取數據的任務。

附錄

生命週期函數:就是vue在某個時間段會自動執行的函數

  1. beforeCreate(){}在執行的時候,data還有methods都沒有被初始化

  2. created(){} data還有methods都被初始化好了,若是要調用 methods 方法或者操做 data 裏面的數據,最先只能在 created 裏面進行操做。

  3. beforeMount(){} 表示模板已經在內存中編輯完成了,可是還沒有渲染到模板頁面中。即頁面中的元素,沒有被真正的替換過來,只是以前寫的一些模板字符串。

  4. mounted(){} 表示內存中模板已經真實的掛載到頁面中去了,用戶能夠看到渲染好的界面了

  • 注意這是一個生命週期函數的最後一個函數了,執行完這個函數表示 整個vue實例已經初始化完成了,組件脫離了建立階段,進入運行階段。

  • 下面是運行期間的兩個生命週期函數的鉤子:

  1. beforeUpdate(){} 表示咱們的界面還沒更新 可是data裏面的數據是最新的。即頁面還沒有和最新的data裏面的數據保持同步。

  2. updated(){} 表示頁面和data裏面的數據已經包吃同步了 都是最新的。

  3. beforeDestory(){} 當執行這個生命週期鉤子的時候 vue的實例從運行階段進入銷燬階段 此時實例身上的data 還有 methods處於可用的狀態。

  4. destoryed(){} 表示組件已經徹底被銷燬了 組件中全部的實例方法都是不能用了

參考:

相關文章
相關標籤/搜索