vue3.x + vue router4.x 緩存方案

需求1:
pageA -> pageB -> pageC
緩存pageB:
pageA進入pageB,刷新頁面并緩存頁面;
pageC返回pageB,不刷新頁面

  1. 在 vuex(或其他存儲方案) 聲明兩個數(shù)組
{
    state: () => ({
        keepAliveViews: [],
        notAliveViews: [],
    }),

    mutations: {
        /**
         * 記錄需要緩存的路由視圖
         */
        saveKeepAliveViews(state, { keepAliveViews }) {
          state.keepAliveViews = keepAliveViews;
        },

        /**
         * 清除頁面緩存
         */
        clearCacheView(state, { notAliveViews }) {
          state.notAliveViews = notAliveViews;
        },
    },
}
  1. 在定義路由時,在meta中添加屬性keepAlive:true
{
    name: "pageB",
    path: "page-b",
    component: () => import("***/pageB.vue"),
    meta: {
        keepAlive: true,
    },
},
  1. 在適當位置遍歷路由表,記錄需要緩存的路由的組件名稱
// 記錄需緩存的路由/組件
const keepAliveViews = [];
router.getRoutes().forEach((routeItem) => {
    if (routeItem?.meta?.keepAlive) {
        // 組件name和路由name保持一致, 所以可以直接使用routeItem.name
        // 也可以在 meta 中添加屬性 compName 來用,或其他方案
        keepAliveViews.push(routeItem.name);
    }
});
store.commit("saveKeepAliveViews", { keepAliveViews });
  1. 在路由根組件中
//  template
<router-view v-slot="{ Component }">
    <keep-alive :include="keepAliveViews" :exclude="notAliveViews">
        <component :is="Component" />
    </keep-alive>
</router-view>
// js
const keepAliveViews = computed(() => store.state.keepAliveViews);
const notAliveViews = computed(() => store.state.notAliveViews);

keep-alive會緩存include中存在的組件,會清除exclude中的組件緩存;

  1. 手動清除組件緩存
/**
 * 清除路由(組件/頁面)緩存
 */
export function clearCacheView(destroyCompNames) {
  store.commit("clearCacheView", { notAliveViews: destroyCompNames });

  // 清除緩存后,要重置數(shù)組為空,下次才能再次緩存
  // 實際上不知道什么時候會完成緩存的清除,這里取500ms,一般滿足需求
  setTimeout(() => {
    store.commit("clearCacheView", { notAliveViews: [] });
  }, 500);
}
{
    name: "pageA",
    path: "page-a",
    component: () => import("***/pageA.vue"),
    meta: {},
    beforeEnter: () => {
      clearCacheView(["pageB"]); // 這里的"pageB"是頁面pageB的組件名稱
    },

返回pageA時,手動清除pageB的緩存;

需求2:
使用緩存頁面,大多數(shù)都是列表頁進入詳情頁,所以還需要考慮列表頁的滾動位置的問題.
即:pageC返回pageB時,pageB要保持在離開時的位置

  1. 在 vuex(或其他存儲方案) 聲明一個數(shù)組
{
    state() {
        return {
            keepAliveViewsScrollPostion: [],
        };
    },

    mutations: {
        // 設置緩存頁面滾動元素的位置
        setkeepAliveViewsScrollPostion(state, { routeName, list }) {
            const item = state.keepAliveViewsScrollPostion.find((t) => t.routeName === routeName);
            if (!item) {
                state.keepAliveViewsScrollPostion.push({ routeName, list });
            } else {
                item.list = list;
            }
        },
    },
}
  1. 在定義路由時,在meta中添加屬性scrollEls
{
    name: "pageB",
    path: "page-b",
    component: () => import("***/pageB.vue"),
    meta: {
      keepAlive: true,
      scrollEls: [".scroll-list"], // 數(shù)組形式,可添加多個可滾動元素
    },
},
  1. 在路由守衛(wèi)中
/**
 * 全局前置守衛(wèi)
 */
router.beforeEach((to, from) => {
  // 緩存頁面:記錄滾動位置
  if (from.meta.scrollEls) {
    const scrollObj: any = { routeName: from.name, list: [] };
    from.meta.scrollEls.forEach((element) => {
      const el = document.querySelector(element);
      if (el) {
        scrollObj.list.push({
          el: element,
          top: el.scrollTop,
        });
      }
    });
    store.commit("setkeepAliveViewsScrollPostion", scrollObj);
  }
});


/**
 * 全局后置鉤子
 */
router.afterEach((to, from) => {
  // 緩存頁面:滾動到指定位置
  nextTick(() => {
    if (to.meta.scrollEls) {
      const item = store.state.keepAliveViewsScrollPostion.find((t) => t.routeName === to.name);
      if (!item) return;
      item.list.forEach((item2) => {
        const el = document.querySelector(item2.el);
        if (el) {
          el.scrollTop = item2.top;
          item2.top = 0;
        }
      });
      // 使用后重置滾動位置為0
      store.commit("setkeepAliveViewsScrollPostion", item);
    }
  });
});
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容