vue3缓存菜单
layout文件
<router-view v-slot="{ Component,route }">
<transition name="el-fade-in-linear" mode="out-in">
<keep-alive :include="include">
<component :is="formatComponentInstance(Component,route.path)" :key="route.path"/>
</keep-alive>
</transition>
</router-view>
const menuTabStore = useMenuTabStore()
//缓存的组件数组 只能使用组件name
const include = computed(()=> menuTabStore.menuTabs.map(item => item.path))
//wrapperMap 缓存已经创建的组件包装器(wrapper)提高性能
let wrapperMap = new Map()
const formatComponentInstance = (component: any, path: string) => {
let wrapper
if (wrapperMap.has(path)) {
wrapper = wrapperMap.get(path)
} else {
wrapper = {
name: path, // 用path生成组件的name,
render:()=> h(component) // h的第一个参数可以是字符串,也可以是一个组件定义;h返回的是一个虚拟dom
}
wrapperMap.set(path, wrapper)
}
return h(wrapper)
}
pinan文件
import { ref } from 'vue'
import { defineStore } from 'pinia'
import router, { type Meta } from '@/router'
export interface MenuTabs {
path: string
meta: Meta
}
export const useMenuTabStore = defineStore(
'menuTabStore',
() => {
// 菜单tabs
const menuTabs = ref<MenuTabs[]>([])
// 激活的tab
const activate = ref('')
function setMenuTabs(routes: MenuTabs[]) {
menuTabs.value = routes
}
function pushMenuTab(route: any) {
const routeCopy = {...route}
if (!menuTabs.value.find((item) => item.path === routeCopy.path)) {
menuTabs.value.push(routeCopy)
}
activate.value = route.path
}
function removeMenuTab(path: string) {
const index = menuTabs.value.findIndex((item) => item.path === path)
menuTabs.value = menuTabs.value.filter((item) => item.path !== path)
if (activate.value === path) {
const activateName = menuTabs.value[index]?.path || menuTabs.value[index - 1]?.path || ''
setActivate(activateName)
}
}
function setActivate(path: string) {
if ((activate.value !== path ) && path) {
router.push({ path })
}
activate.value = path
}
return {
menuTabs,
setMenuTabs,
pushMenuTab,
removeMenuTab,
activate,
setActivate
}
},
{
persist: true
}
)