KeepAlive 示例
1.全部缓存
<router-view v-slot="{ Component }">
<KeepAlive>
<component :is="Component"/>
</KeepAlive>
</router-view>
2.根据路由配置缓存
const routes = [
{
path: '/',
component: () => import('@/views/home/index.vue'),
name: 'home',
meta: {
title: '首页',
keepAlive: true,
},
},
]
const router = createRouter({
history: createWebHashHistory(),
routes,
})
<template>
<router-view v-slot="{ Component, route }">
<keep-alive>
<component :is="Component" :key="$route.fullPath" v-if="route.meta.keepAlive" />
</keep-alive>
<component :is="Component" :key="$route.fullPath" v-if="!route.meta.keepAlive" />
</router-view>
</template>
3.动态控制页面缓存:include
- 通过include匹配实现;
- 要求:值要和页面组件的name一致;
- 方便:为方便取值,页面组件的name要和对应路由name保持一致,直接获取路由的name即可
- 管理:借助pinia进行管理
- 缺点:组件需要手动设置name且和路由一致,麻烦点
- 1、路由:/router/index.js
const routes = [
{
path: '/',
component: () => import('@/views/home/index.vue'),
name: 'home',
meta: {
title: '首页',
keepAlive: true,
},
},
]
const router = createRouter({
history: createWebHashHistory(),
routes,
})
<template>
<router-view v-slot="{ Component, route }">
<keep-alive :include="appStore.cacheList">
<component :is="Component" :key="route.fullPath" />
</keep-alive>
</router-view>
</template>
<script setup>
import { useAppStore } from '@/store/app'
const router = useRouter()
const appStore = useAppStore()
onMounted(() => {
appStore.initCacheList(router)
})
</script>
<style scoped></style>
- 3、pinia实现控制逻辑:/store/app.js
import { defineStore } from 'pinia'
export const useAppStore = defineStore('app', {
state: () => ({
cacheList: []
}),
getters: {
getCacheList: (state) => {
return [...state.cacheList]
},
isCached: (state) => {
return (componentName) => {
return state.cacheList.includes(componentName)
}
}
},
actions: {
initCacheList(router) {
if (!router) {
console.warn('initCacheList: router 参数不能为空')
return
}
router.getRoutes().forEach(route => {
if (route.meta?.keepAlive && route.name) {
const componentName = route.name
if (!this.cacheList.includes(componentName)) {
this.cacheList.push(componentName)
}
}
})
},
addCache(componentName) {
if (!componentName) {
console.warn('addCache: componentName 参数不能为空')
return
}
if (!this.cacheList.includes(componentName)) {
this.cacheList.push(componentName)
console.log(`已添加 ${componentName} 到缓存列表`)
}
},
removeCache(componentName) {
if (!componentName) {
console.warn('removeCache: componentName 参数不能为空')
return
}
const index = this.cacheList.indexOf(componentName)
if (index > -1) {
this.cacheList.splice(index, 1)
console.log(`已移除 ${componentName} 的缓存`)
} else {
console.warn(`未找到 ${componentName} 的缓存`)
}
},
clearAllCache() {
this.cacheList = []
},
autoManageCache(route) {
if (!route) return
const componentName = route.name
if (route.meta?.keepAlive && componentName) {
if (!this.cacheList.includes(componentName)) {
this.addCache(componentName)
}
}
}
}
})
4.解决上面麻烦点
- 动态赋值组件name为路由的name值
- 1.在路由页面/router/index.js 使用工具处理
import { processRoutes } from '@/utils/route-helper';
const routes = [....];
const processedRoutes = processRoutes(routes);
const router = createRouter({
history: createWebHashHistory(),
routes: processedRoutes,
})
export default router;
import { defineComponent, h, markRaw } from 'vue'
export function withRouteName(component, routeName) {
if (!routeName) {
return component
}
if (typeof component === 'function') {
return () => {
return component().then((module) => {
const comp = module.default || module
if (comp.name) {
return module
}
const wrappedComponent = defineComponent({
name: routeName,
setup(props, { slots, attrs }) {
return () => h(comp, { ...props, ...attrs }, slots)
}
})
markRaw(wrappedComponent)
return {
...module,
default: wrappedComponent,
}
})
}
}
if (typeof component === 'object' && component !== null) {
if (component.name) {
return component
}
const wrappedComponent = defineComponent({
name: routeName,
...component
})
markRaw(wrappedComponent)
return wrappedComponent
}
return component
}
export function processRoutes(routes) {
return routes.map(route => {
if (route.name && route.component) {
route.component = withRouteName(route.component, route.name)
}
if (route.children && Array.isArray(route.children)) {
route.children = processRoutes(route.children)
}
return route
})
}
以上已验证
- 登录后 根据接口返回用户可访问的菜单信息 动态添加的路由 缓存功能同样适用