在前端开发中,基于路由参数缓存多个页面实例是一个常见且实用的功能。
比如:在电商项目中,我们可能会有一个商品列表页 /item-list
,当筛选条件或分页参数变化时,想让不同筛选结果被缓存为独立页面,从而在返回时保持页面状态不丢失。
默认的 keep-alive
在缓存时只基于组件名称,不会区分参数,因此在切换参数时,页面状态往往会重置。而我们可以通过动态生成组件名称,结合 keep-alive
和 Map
对象,实现基于参数的多实例缓存,从而在参数变化时缓存多个页面版本。
💡 功能简介
这段代码的核心功能包括:
-
✅ 路由刷新机制
- 通过
provide/inject
实现跨组件调用,可以在其他页面调用刷新当前路由的功能。 - 使用
nextTick
重置router-view
,实现页面的局部刷新。
- 通过
-
✅ 基于参数缓存多个实例
- 通过
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);
};