关于SpringBlade前端UI项目3.x版本路由懒加载和keep-alive三级路由缓存失效优化方案
侧边栏壁纸
  • 累计撰写 5 篇文章
  • 累计收到 37 条评论
VUE

关于SpringBlade前端UI项目3.x版本路由懒加载和keep-alive三级路由缓存失效优化方案

枫叶
2024-12-06 / 8 评论 / 7 阅读 / 正在检测是否收录...

   SpringBlade前端UI项目在使用过程中发现路由并没有懒加载,项目登录成功后所有的资源文件会全部加载,随着项目功能越来越多,首次加载的资源也会越来越多,会造成性能问题。目前最突出的一个问题就是,重新刷新页面,页面会出现空白,随着项目越大,这个空白时间会越长。

  • 基于上面说的问题,我对 /src/router/avue-router.js 文件进行了优化,以下是完整代码。
import website from '@/config/website'

const modules = import.meta.glob('../**/**/*.vue')

// 优化路由懒加载核心代码
const loadPageNotFound = () => {
  return () => import('@/components/error-page/404.vue')
}
const loadView = (view) => {
  let res = null
  for (const path in modules) {
    if (path.indexOf(view) !== -1) {
      res = () => modules[path]()
      return res
    }
  }
  return res
}

function isURL (s) {
  return /^http[s]?:\/\/.*/.test(s)
}
let RouterPlugin = function () {
  this.$router = null;
  this.$store = null;
}
RouterPlugin.install = function (option = {}) {
  this.$router = option.router;
  this.$store = option.store;
  let i18n = option.i18n.global
  this.$router.$avueRouter = {
    safe: this,
    // 设置标题
    setTitle: (title) => {
      const defaultTitle = i18n.t('title');
      title = title ? `${title} | ${defaultTitle}` : defaultTitle;
      document.title = title;
    },
    closeTag: (value) => {
      let tag = value || this.$store.getters.tag;
      if (typeof value === 'string') {
        tag = this.$store.getters.tagList.find(ele => ele.fullPath === value)
      }
      this.$store.commit('DEL_TAG', tag)
    },
    generateTitle: (item, props = {}) => {
      let query = item[props.query || 'query'] || {}
      let title = query.name || item[props.label || 'label']
      let meta = item[props.meta || 'meta'] || {}
      let key = meta.i18n
      if (key) {
        const hasKey = i18n.te('route.' + key)
        if (hasKey) return i18n.t('route.' + key)
      }
      return title.split(',')[0];
    },
    //动态路由
    formatRoutes: function (aMenu = [], first) {
      const aRouter = []
      const propsDefault = website.menu
      if (aMenu && aMenu.length === 0) return;
      for (let i = 0; i < aMenu.length; i++) {
        const oMenu = aMenu[i];
        let path = oMenu[propsDefault.path],
          component = oMenu.component,
          name = oMenu[propsDefault.label] + ',' + oMenu.id,
          icon = oMenu[propsDefault.icon],
          children = oMenu[propsDefault.children],
          query = oMenu[propsDefault.query],
          meta = oMenu[propsDefault.meta];
        if (option.keepAlive) {
          meta.keepAlive = option.keepAlive
        }
        const isChild = !!(children && children.length !== 0);
        const oRouter = {
          path: path,
          component: (() => {
            // 判断是否为首路由
            if (first) {
              return loadView(option.store.getters.isMacOs ? '/page/index/layout.vue' : '/page/index/index.vue')
              // 判断是否为多层路由
            } else if (isChild && !first) {
              return loadView('/page/index/layout.vue')
              // 判断是否为最终的页面视图
            } else {
              let result = loadView(component + '.vue')
              return result || loadPageNotFound()
            }
          })(),
          name,
          icon,
          meta,
          query,
          redirect: (() => {
            if (!isChild && first) return `${path}`
            else return '';
          })(),
          // 处理是否为一级路由
          children: !isChild ? (() => {
            if (first) {
              oMenu[propsDefault.path] = `${path}`;
              let result = loadView(component + '.vue')
              return [{
                component: result || loadPageNotFound(),
                icon: icon,
                name: name,
                meta: meta,
                query: query,
                path: ''
              }]
            }
            return [];
          })() : (() => {
            return this.formatRoutes(children, false)
          })()
        }
        if (!isURL(path)) aRouter.push(oRouter)
      }
      if (first) {
        aRouter.forEach((ele) => this.safe.$router.addRoute(ele))
      } else {
        return aRouter
      }

    }
  }
}
export const formatPath = (ele, first) => {
  const propsDefault = website.menu;
  const icon = ele[propsDefault.icon];
  ele[propsDefault.icon] = !icon ? propsDefault.iconDefault : icon;
  ele.meta = ele.meta || {}
  const iframeComponent = 'components/iframe/main';
  const iframeSrc = (href) => {
    return href.replace(/&/g, "#")
  }
  const isChild = !!(ele[propsDefault.children] && ele[propsDefault.children].length !== 0);
  if (!isChild && first) {
    ele.component = 'views' + ele[propsDefault.path]
    if (isURL(ele[propsDefault.href])) {
      let href = ele[propsDefault.href]
      ele.component = iframeComponent
      ele[propsDefault.query] = { url: iframeSrc(href) }
    }
  } else {
    ele[propsDefault.children] && ele[propsDefault.children].forEach(child => {
      child.component = 'views' + child[propsDefault.path]
      if (isURL(child[propsDefault.href])) {
        let href = child[propsDefault.href]
        child[propsDefault.path] = ele[propsDefault.path] + '/' + child.code
        child.component = iframeComponent
        child[propsDefault.query] = { url: iframeSrc(href) }
      }
      formatPath(child);
    })
  }
}
export default RouterPlugin;
  • keep-alive 三级菜单失效解决方案,可在 /src/permission.js 文件中修改,以下是代码片段。
router.beforeEach((to, from, next) => {
  const meta = to.meta || {};
  const isMenu = meta.menu === undefined ? to.query.menu : meta.menu;
  store.commit('SET_IS_MENU', isMenu === undefined);
  if (getToken()) {

    // 三级菜单组件无法缓存问题
    if (to.matched && to.matched.length > 2) {
      to.matched.splice(1, to.matched.length - 2)
    }
    ......
以上就是SpringBlade前端UI项目3.x版本优化的具体方案。
本文共 243 个字数,平均阅读时长 ≈ 1分钟
0

评论 (8)

取消
  1. 头像
    csnmdmfgml
    Windows 10 · Google Chrome

    作者的才华横溢,让这篇文章成为了一篇不可多得的艺术品。

    回复
  2. 头像
    zhuctomhzj
    Windows 10 · Google Chrome

    新盘 上车集合 留下 我要发发 立马进裙

    回复
  3. 头像
    xmtbpnevyy
    Windows 10 · Google Chrome

    新车上路,只带前10个人coinsrore.com

    回复
  4. 头像
    zmbknzpivc
    Windows 10 · Google Chrome

    2025年10月新盘 做第一批吃螃蟹的人coinsrore.com
    新车新盘 嘎嘎稳 嘎嘎靠谱coinsrore.com
    新车首发,新的一年,只带想赚米的人coinsrore.com
    新盘 上车集合 留下 我要发发 立马进裙coinsrore.com
    做了几十年的项目 我总结了最好的一个盘(纯干货)coinsrore.com
    新车上路,只带前10个人coinsrore.com
    新盘首开 新盘首开 征召客户!!!coinsrore.com
    新项目准备上线,寻找志同道合 的合作伙伴coinsrore.com
    新车即将上线 真正的项目,期待你的参与coinsrore.com
    新盘新项目,不再等待,现在就是最佳上车机会!coinsrore.com
    新盘新盘 这个月刚上新盘 新车第一个吃螃蟹!coinsrore.com

    回复
  5. 头像

    果博东方客服开户联系方式【182-8836-2750—】?薇- cxs20250806】
    果博东方公司客服电话联系方式【182-8836-2750—】?薇- cxs20250806】
    果博东方开户流程【182-8836-2750—】?薇- cxs20250806】
    果博东方客服怎么联系【182-8836-2750—】?薇- cxs20250806】

    回复
  6. 头像

    果博东方客服开户联系方式【182-8836-2750—】?薇- cxs20250806】
    果博东方公司客服电话联系方式【182-8836-2750—】?薇- cxs20250806】
    果博东方开户流程【182-8836-2750—】?薇- cxs20250806】
    果博东方客服怎么联系【182-8836-2750—】?薇- cxs20250806】

    回复
  7. 头像

    华纳圣淘沙公司开户新手教程

    零基础学会(183-8890-9465薇-STS5099)
    华纳圣淘沙公司开户

    华纳圣淘沙公司开户保姆级教程(183-8890-9465薇-STS5099)

    一步步教你开通华纳圣淘沙公司账户(183-8890-9465薇-STS5099)

    华纳圣淘沙公司开户分步图解

    首次开户必看:(183-8890-9465薇-STS5099)
    华纳圣淘沙全攻略

    华纳圣淘沙公司开户实操手册(183-8890-9465薇-STS5099)
    华纳圣淘沙开户流程视频教程

    手把手教学:(183-8890-9465薇-STS5099)
    华纳圣淘沙公司开户

    华纳圣淘沙公司开户完全指南(183-8890-9465薇-STS5099)

    回复
  8. 头像

    华纳圣淘沙公司开户新手教程

    零基础学会(183-8890-9465薇-STS5099)
    华纳圣淘沙公司开户

    华纳圣淘沙公司开户保姆级教程(183-8890-9465薇-STS5099)

    一步步教你开通华纳圣淘沙公司账户(183-8890-9465薇-STS5099)

    华纳圣淘沙公司开户分步图解

    首次开户必看:(183-8890-9465薇-STS5099)
    华纳圣淘沙全攻略

    华纳圣淘沙公司开户实操手册(183-8890-9465薇-STS5099)
    华纳圣淘沙开户流程视频教程

    手把手教学:(183-8890-9465薇-STS5099)
    华纳圣淘沙公司开户

    华纳圣淘沙公司开户完全指南(183-8890-9465薇-STS5099)

    回复