vue移動端專案快取問題實踐

rocky191發表於2018-10-28

最近在做一個vue移動端專案,被快取問題搞得頭都大了,積累了一些經驗,特此記錄總結下,權當是最近專案問題的一個回顧吧!

先描述下問題場景:A頁面->B頁面->C頁面。假設A頁面是列表頁面,B頁面是列表詳情頁面,C頁面是操作改變B頁面的一些東西,進行提交類似的操作。A頁面進入B頁面,應該根據不同的列表item顯示不一樣的詳情,從B進入C,也應該根據item的標識比如ID展示不一樣的內容,在C頁面操作後,返回B頁面,B頁面資料發生變化。這個時候會有兩種情況:

  • C頁面運算元據後返回B頁面,B頁面對應資料應該發生變化。
  • C頁面直接點選左上角箭頭返回,B頁面對應資料不應該發生變化。繼續返回A列表頁面,換一條資料,繼續進入B頁面,B頁面展示不同內容,進入C頁面,C頁面重新整理展示不同內容

另一種情況發生在寫郵件的頁面中,新增收件人,選人之後,繼續新增,之前新增的聯絡人應該存在。但是從寫郵件頁面返回郵件列表再次進入寫郵件頁面,之前新增過的聯絡人資料就不應該存在了,這裡就涉及到如何處理快取,何時使用快取,何時清除快取的問題了。

目前專案整體結構如下:

<template>
  <div id="app">
    <keep-alive>
      <router-view v-if="$route.meta.keepAlive"></router-view>
    </keep-alive>
    <router-view v-if="!$route.meta.keepAlive"></router-view>
  </div>
</template>
複製程式碼

雖然官方提供了include,exclude,可以讓我們決定哪些元件使用快取,哪些不使用快取,但是並沒有解決我們想動態使用快取的目的,目前我的專案使用瞭如下兩種方式處理快取:

方式一 ,使用是否使用快取標識

在路由檔案router.js裡給每個路由新增meta資訊,標識是否使用快取。

meta: {
    isUseCache: false,//不使用快取
    keepAlive: true
}
複製程式碼

使用方式:
A->B,B不能快取;B->A,A快取。

  • (1)A頁面:
beforeRouteLeave(to, from, next) {
  // 設定下一個路由的 meta
  if(to.path=='/B'){
    to.meta.isUseCache = false;
  }
  next();
},
activated(){
    if(!this.$route.meta.isUseCache){
        this.getData();
    }
}  
複製程式碼
  • (2) B頁面
beforeRouteLeave(to, from, next) {
  // 設定下一個路由的 meta
  if(to.path=='/A'){
    to.meta.isUseCache = true;
  }
  next();
},
activated(){
    if(!this.$route.meta.isUseCache){
        this.getData();
    }
}  
複製程式碼

方式二,強制清除快取。

這種方式是從網上找的一種方式,使用了vue內部元件之後,不在支援動態銷燬元件,快取一直存在,只能從源頭上下手,清掉快取。

export const removeCatch = {
  beforeRouteLeave:function(to, from, next){
    if (from && from.meta.rank && to.meta.rank && from.meta.rank>to.meta.rank)
      {//此處判斷是如果返回上一層,你可以根據自己的業務更改此處的判斷邏輯,酌情決定是否摧毀本層快取。
          if (this.$vnode && this.$vnode.data.keepAlive)
          {
              if (this.$vnode.parent && this.$vnode.parent.componentInstance && this.$vnode.parent.componentInstance.cache)
              {
                  if (this.$vnode.componentOptions)
                  {
                      var key = this.$vnode.key == null
                                  ? this.$vnode.componentOptions.Ctor.cid + (this.$vnode.componentOptions.tag ? `::${this.$vnode.componentOptions.tag}` : '')
                                  : this.$vnode.key;
                      var cache = this.$vnode.parent.componentInstance.cache;
                      var keys  = this.$vnode.parent.componentInstance.keys;
                      if (cache[key])
                      {
                          if (keys.length) {
                              var index = keys.indexOf(key);
                              if (index > -1) {
                                  keys.splice(index, 1);
                              }
                          }
                          delete cache[key];
                      }
                  }
              }
          }
          this.$destroy();
      }
      next();
  }
};

複製程式碼

在需要清掉快取的頁面混合引入該js即可。 原文連結

結語

移動端的快取真是麻煩啊,前進後退,什麼時候使用快取,什麼時候不使用快取,都需要經過仔細的處理,不然就會有想不到的問題。不過經過這次專案,也積累了一定的經驗。如果有大佬有別的更好的解決辦法,還請告知,多謝!還是那句話,有問題就去解決,不要害怕問題,解決了問題,你就會成長!

順帶推廣一下自己部落格,同步更新!

相關文章