Vben Admin 多标签页状态管理源码学习

 更新时间:2022年09月01日 11:23:27   作者:Andurils  
这篇文章主要为大家介绍了Vben Admin 多标签页状态管理源码学习,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

引言

本文将对 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中设置ignoreKeepAlivetrue,该标签页不会被缓存。

// 根据当前打开的标签更新缓存
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 多标签页状态管理的资料请关注脚本之家其它相关文章!

相关文章

  • vue2源码解析之全局API实例详解

    vue2源码解析之全局API实例详解

    全局API并不在构造器里,而是先声明全局变量或者直接在Vue上定义一些新功能,Vue内置了一些全局API,下面这篇文章主要给大家介绍了关于vue2源码解析之全局API的相关资料,需要的朋友可以参考下
    2022-11-11
  • Vue3 + Vue-PDF 实现PDF 文件在线预览实战

    Vue3 + Vue-PDF 实现PDF 文件在线预览实战

    这篇文章主要介绍了Vue3 + Vue-PDF 实现PDF 文件在线预览实战,文章围绕主题展开详细的内容介绍,具有一定的参考价值,需要的小伙伴可以参考一下
    2022-06-06
  • vue实现顶部菜单栏

    vue实现顶部菜单栏

    这篇文章主要为大家详细介绍了vue实现顶部菜单栏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-11-11
  • vueJs函数readonly与shallowReadonly使用对比详解

    vueJs函数readonly与shallowReadonly使用对比详解

    这篇文章主要为大家介绍了vueJs函数readonly与shallowReadonly使用对比详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-03-03
  • Vue3菜单展开和收起实现

    Vue3菜单展开和收起实现

    在Vue项目中实现首页布局,包括可收放的左侧菜单和主体内容区,在store中管理菜单状态,通过修改isCollapse状态控制菜单的展开与收起,在home.vue中编写左侧菜单栏的代码和样式,实现一个响应式的用户界面
    2024-09-09
  • Vue实现搜索结果高亮显示关键字

    Vue实现搜索结果高亮显示关键字

    这篇文章主要为大家详细介绍了Vue实现搜索结果高亮显示关键字,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-05-05
  • vue微信分享到朋友圈 vue微信发送给好友

    vue微信分享到朋友圈 vue微信发送给好友

    这篇文章主要为大家详细介绍了vue微信分享到朋友圈,vue微信发送给好友功能,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-11-11
  • 在vue中使用 jquery 的两种方法小结

    在vue中使用 jquery 的两种方法小结

    这篇文章主要介绍了在vue中使用 jquery 的两种方法小结,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-08-08
  • Vue中 引入使用 babel-polyfill 兼容低版本浏览器的方法

    Vue中 引入使用 babel-polyfill 兼容低版本浏览器的方法

    最近在项目中使用 webpack 打包后升级,用户反馈使用浏览器(chrome 45)访问白屏。经过排查发现:由于 chrome 45 无法兼容 ES6 语法导致的,接下来给大家介绍下Vue中 引入使用 babel-polyfill 兼容低版本浏览器方法,需要的朋友可以参考下
    2023-02-02
  • 前端登录退出处理Token问题(获取、缓存、失效处理)及代码实现方法

    前端登录退出处理Token问题(获取、缓存、失效处理)及代码实现方法

    token是一个用户信息的表示,在登录中将会从后端拿到token,然后用户才可以进行往后的一系列操作,这篇文章主要给大家介绍了关于前端登录退出处理Token问题(获取、缓存、失效处理)及代码实现的相关资料,需要的朋友可以参考下
    2024-01-01

最新评论