引言
本文将对 Vue-Vben-Admin 的状态管理实现源码进行分析解读,耐心读完,相信您一定会有所收获!
multipleTab.ts 系统锁屏
文件 src\store\modules\multipleTab.ts
声明导出一个store实例 useMultipleTabStore
、一个方法 useMultipleTabWithOutStore()
用于没有使用 setup
组件时使用。
// 多标签页信息存储 export const useMultipleTabStore = defineStore({ id: 'app-multiple-tab', state: { /*...*/ }, getters: { /*...*/ } actions:{ /*...*/ } }); export function useMultipleTabWithOutStore() { return useMultipleTabStore(store); }
State/Getter
状态对象定义了标签页路由列表、缓存标签页名称以及最后一次拖动标签的索引。同时提供了对应方法用于获取该状态值。
// 多标签页状态 export interface MultipleTabState { cacheTabList: Set<string>; // 缓存标签页路由名称 // 标签页路由列表 RouteLocationNormalized 路由记录的标准化版本 tabList: RouteLocationNormalized[]; lastDragEndIndex: number; // 最后一次拖动标签的索引 } state: (): MultipleTabState => ({ cacheTabList: new Set(), tabList: cacheTab ? Persistent.getLocal(MULTIPLE_TABS_KEY) || [] : [], // 优先加载缓存/本地存储内容 lastDragEndIndex: 0, }), getters: { // 获取标签页路由列表 getTabList(): RouteLocationNormalized[] { return this.tabList; }, // 获取缓存标签页路由名称列表 getCachedTabList(): string[] { return Array.from(this.cacheTabList); }, // 获取最后一次拖动标签的索引 getLastDragEndIndex(): number { return this.lastDragEndIndex; }, },
Actions
方法 addTab
方法用于打开标签页。
- 判断当前打开是否特殊页面(错误处理/登录/重定向)。
- 若存在已经打开路径相同的标tianj签页,更新其标签页路由记录,否则添加新页面路由记录。
- 更新需要缓存的标签页路由名称,使用本地存储持久化。
// 打开标签页 async addTab(route: RouteLocationNormalized) { // 路由基本属性 const { path, name, fullPath, params, query, meta } = getRawRoute(route); // 错误处理页面 登录 重定向 等页面 if ( path === PageEnum.ERROR_PAGE || path === PageEnum.BASE_LOGIN || !name || [REDIRECT_ROUTE.name, PAGE_NOT_FOUND_ROUTE.name].includes(name as string) ) { return; } let updateIndex = -1; // 标签页已经存在,不在重复添加标签 const tabHasExits = this.tabList.some((tab, index) => { updateIndex = index; return (tab.fullPath || tab.path) === (fullPath || path); }); // 标签已经存在,执行更新操作 if (tabHasExits) { const curTab = toRaw(this.tabList)[updateIndex]; // 获取当前标签页路由记录 if (!curTab) { return; } curTab.params = params || curTab.params; // 从 path 中提取的已解码参数字典 curTab.query = query || curTab.query; // 从 URL 的 search 部分提取的已解码查询参数的字典。 curTab.fullPath = fullPath || curTab.fullPath; // URL 编码与路由地址有关。包括 path、 query 和 hash。 this.tabList.splice(updateIndex, 1, curTab); // 替换原有的标签页路由记录 } else { // 添加标签页 // 获取动态路由打开数,超过 0 即代表需要控制打开数 const dynamicLevel = meta?.dynamicLevel ?? -1; if (dynamicLevel > 0) { // 如果设置大于 0 了,那么就要限制该路由的打开数限制了 // 首先获取到真实的路由,使用配置方式减少计算开销. // const realName: string = path.match(/(\S*)\//)![1]; const realPath = meta?.realPath ?? ''; // 获取到已经打开的动态路由数, 判断是否大于某一个值 if ( this.tabList.filter((e) => e.meta?.realPath ?? '' === realPath).length >= dynamicLevel ) { // 关闭第一个 const index = this.tabList.findIndex((item) => item.meta.realPath === realPath); index !== -1 && this.tabList.splice(index, 1); } } this.tabList.push(route); // 添加至路由列表中 } this.updateCacheTab(); // 使用本地存储持久化 cacheTab && Persistent.setLocal(MULTIPLE_TABS_KEY, this.tabList); },
方法updateCacheTab
用于更新需要缓存的标签页路由名称,返回一个 Set 集合。若路由中meta
中设置ignoreKeepAlive
为 true
,该标签页不会被缓存。
// 根据当前打开的标签更新缓存 async updateCacheTab() { // Set 集合存储 const cacheMap: Set<string> = new Set(); for (const tab of this.tabList) { const item = getRawRoute(tab); // 若忽略KeepAlive缓存 不缓存 const needCache = !item.meta?.ignoreKeepAlive; if (!needCache) { continue; } const name = item.name as string; cacheMap.add(name); } this.cacheTabList = cacheMap; // 存储路由记录名称的 Set 集合 },
方法setTabTitle
使用meta
属性,将最新标题内容附加到路由上。
// 设置标签标题 async setTabTitle(title: string, route: RouteLocationNormalized) { const findTab = this.getTabList.find((item) => item === route); if (findTab) { findTab.meta.title = title; // meta实现 设置每个页面的title标题 await this.updateCacheTab(); } },
在标签页组件中,根据传入打开页面路由记录tabItem
,标签页标题名称绑定计算属性 getTitle
。
// src\layouts\default\tabs\components\TabContent.vue <template> <Dropdown :dropMenuList="getDropMenuList" :trigger="getTrigger" @menu-event="handleMenuEvent"> <div :class="`${prefixCls}__info`" @contextmenu="handleContext" v-if="getIsTabs"> <span class="ml-1">{{ getTitle }}</span> </div> </Dropdown> </template> props: { tabItem: { type: Object as PropType<RouteLocationNormalized>, default: null, }, isExtra: Boolean, }, // 获取标题信息 const getTitle = computed(() => { const { tabItem: { meta } = {} } = props; return meta && t(meta.title as string); });
以上就是Vben Admin 多标签页状态管理源码学习的详细内容,更多关于Vben Admin 多标签页状态管理的资料请关注阿兔在线工具其它相关文章!