vue.js

关注公众号 jb51net

关闭
首页 > 网络编程 > JavaScript > javascript类库 > vue.js > vue3+vite动态加载路由,本地路由和线上路由匹配

vue3+vite动态加载路由,本地路由和线上路由匹配方式

作者:arno-cai

这篇文章主要介绍了vue3+vite动态加载路由,本地路由和线上路由匹配方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

使用场景

本地全路由动态匹配线上路由

目的

本地路由方便开发配置,匹配线上路由,进行页面路由控制

内容

// router/constRoutes.js
// ---------------------------------------
// constRoutes 固定需要加载的路由,
// notFound 动态路由加载完成后再添加,否则刷新页面,此时还没有路由,会直接定向到notFound页面
// ---------------------------------------
export const constRoutes = [
  {
    path: '/',
    redirect: '/home'
  },
  {
    path: '/home',
    name: 'home',
    component: () => import('@/views/home/index.vue')
  },
  {
    path: '/login',
    name: 'login',
    component: () => import('@/views/login/index.vue')
  }
]
export const notFound = {
  path: '/:pathMatch(.*)*',
  name: 'notFound',
  component: () => import('@/views/not-found/not-found.vue')
}
// router/asyncRoutes.js
// ---------------------------------------
// 注意:children下的path不需要加'/'
// meta下可以加各种本地你想要的参数
// ---------------------------------------
const Layout = () => import('@/layout/index.vue')
export const asyncRoutes = [
  {
    path: '/monitoringCenter',
    name: 'MonitoringCenter',
    component: Layout,
    meta: { title: '监控中心' },
    children: [
      {
        path: 'carMonitoring',
        name: 'CarMonitoring',
        meta: { title: '车辆监控' },
        children: [
          {
            path: 'positioning',
            name: 'Positioning',
            component: () => import('@/views/monitoringCenter/positioning/index.vue'),
            meta: { title: '实时定位' }
          }
        ]
      },
      {
        path: 'monitorSetting',
        name: 'MonitorSetting',
        meta: { title: '监控设置' },
        children: [
          {
            path: 'ruleManagement',
            name: 'RuleManagement',
            component: () => import('@/views/monitoringCenter/ruleManagement/index.vue'),
            meta: { title: '报警规则' }
          }
        ]
      }
    ]
  },
// router/index.js
// ---------------------------------------
// 先加载constRoutes 固定路由
// ---------------------------------------
import { createRouter, createWebHistory } from 'vue-router'
import { constRoutes } from '@/router/constRoutes'
const router = createRouter({
  history: createWebHistory(import.meta.env.BASE_URL),
  routes: constRoutes
})
export default router
// utils/map-menus.js
// ---------------------------------------
//导出方法,menuList是线上路由,Routes第一次默认是本地路由
// ---------------------------------------
import { asyncRoutes } from '@/router/asyncRoutes'
// 添加redirect重定向
let redirect = ''
// 匹配路由,添加对应线上传回来的参数
export function mapMenusToRoutes(menuList, Routes = asyncRoutes) {
  const routes = []
  for (let item of Routes) {
    const m = menuList.find((menu) => item.name == menu.name)
    if (m) {
    // 线上按钮权限放在attr中
      m.attr && m.attr.length && (item.attr = m.attr)
      item.id = m.id
      // ‘?.'判断是否有children且大于零
      if (item.children?.length) {
          // 添加重定向
        if (item.path.includes('/')) {
          redirect = item.path
          item.redirect = `${redirect}/${item.children[0].path}`
        } else {
          item.redirect = `${redirect}/${item.path}/${item.children[0].path}`
        }
        // 如果有children 则回调并赋值
        item.children = mapMenusToRoutes(m.children, item.children)
      }
      routes.push(item)
    }
  }
  return routes
}

&&&&后面是具体调用方式,因人而异,可自行选择

// stores/login.js
import { defineStore } from 'pinia'
import router from '@/router'
import { notFound } from '@/router/constRoutes'
import localCache from '@/utils/cache'
import { mapMenusToRoutes } from '@/utils/map-menus'
import { login, getInfo } from '@/api/user/login'
export const useLoginStore = defineStore({
  id: 'useLoginStore',
  state: () => ({
    token: '',
    menuList: [],
    routeMenus: []
  }),
  getters: {
    routeMenusGet() {
      return this.routeMenus
    }
  },
  actions: {
    async LoginAction(loginForm) {
      // 1.实现登录逻辑
      const { data: loginData } = await login(loginForm)
      this.token = loginData.token
      // 保存至localStorage,方法随意
      localCache.setCache('token', this.token)
      // 2.跳转至首页
      router.push('/home')
    },
    // router.beforeEach获取菜单树
    async getInfoAction() {
      const infoData = await getInfo({ token: this.token })
      this.menuList = infoData.data.menuList
      this.addRouteMenus()
    },
    // 动态加载路由
    addRouteMenus() {
      this.routeMenus = mapMenusToRoutes(this.menuList)
      // vue3中只有addRoute
      for (let item of this.routeMenus) {
        router.addRoute(item)
      }
      // 最后添加,否则刷新请求线上路由时,还没有加载完,会直接定向到notFound
      router.addRoute(notFound)
    }
  }
})
// src/permission.js
// main.js中引入次文件 import '@/permission'
import router from './router'
import localCache from '@/utils/cache'
import { useLoginStore } from '@/stores/user/login'
router.beforeEach(async (to, from, next) => {
  document.title = `${to.meta.title}`
  if (to.path === '/login') {
      // 清空localStorage
    localCache.clearCache()
    next()
  } else {
    const token = localCache.getCache('token')
    if (!token) {
      next(`/login`)
    } else {
      const loginStore = useLoginStore()
      if (loginStore.routeMenus.length) {
        next()
      } else {
      // 如果没有路由,调用动态加载路由
        try {
          await loginStore.getInfoAction()
          next({ ...to, replace: true })
        } catch (error) {
          next(`/login`)
        }
      }
    }
  }
})

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

您可能感兴趣的文章:
阅读全文