vue3中,如何将keep-alive的同一个路由页面,根据不同的参数缓存为多个页面?

145 阅读2分钟

在前端开发中,基于路由参数缓存多个页面实例是一个常见且实用的功能。
比如:在电商项目中,我们可能会有一个商品列表页 /item-list,当筛选条件或分页参数变化时,想让不同筛选结果被缓存为独立页面,从而在返回时保持页面状态不丢失。

默认的 keep-alive 在缓存时只基于组件名称,不会区分参数,因此在切换参数时,页面状态往往会重置。而我们可以通过动态生成组件名称,结合 keep-aliveMap 对象,实现基于参数的多实例缓存,从而在参数变化时缓存多个页面版本。


💡 功能简介

这段代码的核心功能包括:

  1. 路由刷新机制

    • 通过 provide/inject 实现跨组件调用,可以在其他页面调用刷新当前路由的功能。
    • 使用 nextTick 重置 router-view,实现页面的局部刷新。
  2. 基于参数缓存多个实例

    • 通过 fullPath 拼接缓存名称,生成唯一标识,让 keep-alive 将同一页面的不同参数视为多个独立页面缓存
    • 使用 Map 对象存储生成的页面包装器,避免重复创建组件实例。

🛠️ 适用场景

  • 在商品列表页按筛选条件缓存多个页面版本,避免切换筛选条件时丢失页面状态。
  • 多标签管理:在后台管理系统中,每个标签页缓存独立的页面实例,避免数据丢失。
  • 优化用户体验:提高页面返回时的流畅性,减少重复加载。

✅ 接下来,让我们详细解析这段代码的实现逻辑! 🚀

    <router-view v-slot="{ Component }" v-if="isRouterActive">
            <transition name="component-fade" mode="out-in">
              <keep-alive :include="caches" :max="10">
                <component :is="wrap(Component,route.name, route.fullPath)" />
              </keep-alive>
            </transition>
          </router-view>    

script

const isRouterActive = ref(true);
//这个代码作用是在其他地方调用刷新当前路由页面
provide("reload", () => {
  isRouterActive.value = false;
  nextTick(() => {
    isRouterActive.value = true;
  });
});

const caches = ref("");
const wrapperMap = new Map();
const wrap = (component,name,fullPath) => {
  let wrapper;
  let wrapperName = name;

  //假设要缓存的路由页面是/item-list
  if(fullPath.indexOf('item-list')!=-1&&fullPath!=='/item-list'){
  //根据fullpath进行缓存
     wrapperName = fullPath;
    if(caches.value.indexOf(fullPath)==-1){
      caches.value+=','+fullPath
    }

  }
  if (wrapperMap.has(wrapperName)) {
    wrapper = wrapperMap.get(wrapperName);
  } else {
    wrapper = {
      name: wrapperName,
      render() {
        return h("div", {}, component);
      },
    };
    wrapperMap.set(wrapperName, wrapper);
  }
  return h(wrapper);
};