Vue中使用Keep-Alive實現複雜頁面緩存

Keep-alive

vue2.0中提供了一個keep-alive的組建來緩存組件,避免屢次加載相應的組件,減小性能消耗。vue

keep-alive是Vue的內置組件,能在組件切換過程當中將狀態保留在內存中,防止重複渲染DOM,結合vue-router中使用。能夠緩存某個view的整個內容。正則表達式

語法:vue-router

<keep-alive>
    <component>
        <!-- 須要緩存的組件 -->
    </component>
</keep-alive>
複製代碼

通常有這種需求的都是,第一次進入頁面時請求一次數據,後面經過路徑切換或者前進/後退進入改頁面時,頁面都使用的緩存數據,DOM不會刷新。緩存

prop
  • include: 字符串或正則表達式。只有匹配的組件會被緩存。
  • exclude: 字符串或正則表達式。任何匹配的組件都不會被緩存。
條件緩存 【prop】
<!-- a.vue -->
export default {
    name: 'test',
    data() {
        return {
            includedComponents: 'test'
        }
    }
}
複製代碼

結合exclude和include來進行條件緩存bash

<keep-alive include="test">
  <!-- 將緩存name爲test的組件 -->
  <component></component>
</keep-alive>

<keep-alive include="a,b">
  <!-- 將緩存name爲a或者b的組件,結合動態組件使用 -->
  <component :is="view"></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>

<keep-alive exclude="test">
  <!-- 將不緩存name爲test的組件 -->
  <component></component>
</keep-alive>
複製代碼
部分緩存【keepAlive屬性】

咱們可能會碰到這樣的需求,部分緩存:性能

主頁 - 列表頁 - 詳情頁
主頁 => 列表頁 【列表頁不須要緩存】
詳情頁 => 列表頁 【列表頁須要緩存】
複製代碼

網上有不少關於這個例子的解決方案,可是你們有沒有發現這種處理方法存在問題,代碼大概是這樣的。ui

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

list頁面路由this

{
        path: '/list',
        name: 'list',
        component: list,
        meta: {
            keepAlive: true,
        }
    }
複製代碼

Home頁面設置spa

<!-- home.vue -->
export default {
    data() {
        return {};
    },
    methods: {},
    beforeRouteLeave(to, from, next) {
         // 設置下一個路由的 meta
        to.meta.keepAlive = false;  
        // Home 跳轉到 list 時,讓 list 不緩存,即刷新
        next();
    }
};
複製代碼

detail頁面prototype

<!-- detail.vue -->
export default {
    data() {
        return {};
    },
    methods: {},
    beforeRouteLeave(to, from, next) {
         // 設置下一個路由的 meta
        to.meta.keepAlive = true;  
        // detail 跳轉到 list 時,讓 list 緩存,即不刷新
        next();
    }
}; 
複製代碼

這種方案的bug:

  1. 首次從 Home => list[頁面刷新] => detail;
  2. 目前咱們處於detail頁面;
  3. detail => list[頁面刷新] 【爲何呢?由於咱們在Home =>list時將list的keepAlive設置爲false了】;
  4. 當前處於list頁面,
  5. 再次從 list => detail ,而後返回 detail => list[頁面沒有刷新],緩存成功。

也就是說只要從 Home => list,list的緩存設置失效,必須經歷一次detail => list 才能將keepAlive設置爲true,list才能達到緩存效果。

結合Keep-alive實現複雜緩存

今天想說的重點 最近有一個需求是這樣的:

A_1 => A [A頁面須要緩存]
B_1 => B [B頁面須要緩存]
A => B [B不須要緩存]
B => A [A不須要緩存]
複製代碼

這種需求怎麼實現呢?最開始的想法是更改keepAlive的方式,最後發現行不通。最後的解決方案是

  1. 將A,B頁面設置爲緩存頁面
  2. 記錄頁面的跳轉,即上一個頁面是哪個。
  3. 在A,B頁面中判斷上一個頁面不是A_1或者B_1是就手動刷新頁面【activated】階段,由於頁面緩存後第二次進入是不會進入created和mounted的。

具體代碼: 路由設置

{
    path: '/A',
    name: 'A',
    component: A,
    meta: {
        keepAlive: true,
    }
 },
 {
    path: '/B',
    name: 'B',
    component: B,
    meta: {
        keepAlive: true,
    }
 }
複製代碼

main.js中記錄上一個路由地址

router.beforeEach((to, from, next) => {
    Vue.prototype.beforeRouter = from;
    next();
})
複製代碼

A.vue頁面,

activated() {
    const beforeRouterName = this.beforeRouter.name;
    if (beforeRouterName && beforeRouterName !== 'A_1') {
        // 手動刷新頁面
        this.$refs.table.reload();
    }
 },
複製代碼

B.vue頁面

activated() {
    const beforeRouterName = this.beforeRouter.name;
    if (beforeRouterName && beforeRouterName !== 'B_1') {
        // 手動刷新頁面
        this.$refs.table.reload();
    }
 },
複製代碼

這樣就能夠實現只要不是B_1/A_1頁面進入到B/A時均可以將頁面刷新。可能不是最好的解決方案,

若是你有什麼更好的解決方法能夠留言; 查看更多相關信息可關注公衆號:

相關文章
相關標籤/搜索