接后端接口静态路由+动态路由

一般来说,[前端项目] 中的路由,很有可能是需要动态注册的。因为菜单可能在管理系统中维护,还跟权限绑定,用户登录以后,需要动态展示菜单。菜单往往跟路由挂钩,因此,路由需要动态注册

那么就分为前端默认路由 和 后端接口动态路由

1.前端默认路由 可以存放一些 登录页面 404 等公共页面
2.后端接口动态路由,就是根据用户的权限展示那些页面,由接口决定,在通过 router.addRoute 进行添加
  1. 在前端项目中 router 文件夹下面创建 index.js
javascript 复制代码
import Vue from 'vue'
import VueRouter from 'vue-router'
import Main from '@/views/Main'
import Role1 from '@/views/role/role1'
import store from '@/store'
Vue.use(VueRouter)

// 静态路由
export const constantRoutes = [
    {
        path: '/login',
        name: 'login',
        component: () =>
            import( "@/views/LoginPage"),
        meta: {
            keepAlive: true,
            isTab: false,
            isAuth: false,
        },
    },
    {
        path: '/',
        component: Main,
        name: 'Main',
        redirect: '/home',
        children: [
        ]
    },
    {
        path: '/404',
        name: '404',
        component: () =>
            import('@/views/error/404'),
        hidden: true
    },
    {
        path: '/401',
        name: '401',
        component: () =>
            import( '@/views/error/401'),
        hidden: true
    },
   // {
   //     path: "*",
   //     redirect: "/404",
   // },

]


const router = new VueRouter({
    mode: 'hash',
    scrollBehavior: () => ({ y: 0 }),
    routes:constantRoutes
})

// 解决ElementUI报重复点击菜单错误
const originalPush = router.push
router.push = function push(location) {
    return originalPush.call(this, location).catch(err => err)
}

export default router

这里需要注意一下

  1. 我把获取用户信息的接口放入到了 vuex
javascript 复制代码
import { login, logout, getInfo } from '@/api/login'
import { getStore, setStore, clearStore, removeStore } from '@/util/storage'
import { deepClone } from '@/util/validate'
import router from '@/router';
// 动态菜单 多层嵌套
const generateRoutes = (menuList, parentPath = '') => {
  return menuList.map(menuItem => {
    const fullPath = parentPath + menuItem.menuPath;
    const route = {
      path: fullPath,
      component: () => import(`@/views/${menuItem.menuComponentPath}`),
      name: menuItem.menuName,
      meta: { title: menuItem.menuTitle, noCache: true, icon: menuItem.menuIconName },
      id: menuItem.id
    };

    if (menuItem.children && menuItem.children.length > 0) {
      route.children = generateRoutes(menuItem.children, fullPath + '/');
    }
    router.addRoute("Main",route);
    return route;
  });
};

// 扁平化动态路由
const flattening=(menuTree)=>{
  console.log(menuTree,'menuTree');
  let tempArray =[]
  menuTree.forEach(ele=>{
    tempArray.push(ele)
    // 递归处理
    if (ele.children) {
      tempArray.push(...flattening(ele.children));
    }
  })
  return tempArray
}

const user = {
  state: {
    meun:getStore({
      name: 'menu'
    }) || [],
  },

  mutations: {
    SET_MENU(state, menu) {
      state.menu = menu
      setStore({
        name: 'menu',
        content: menu,
        type: 'session'
        
      })
    },
 
  },

  actions: {
  
    // 获取用户信息 
    GetInfo({ commit, state }) {
      return new Promise((resolve, reject) => {
        getInfo().then(res => {
          console.log(res.data, 'GetInfo');
          const menu = deepClone(res.data.menus);
          const menus = generateRoutes(menu); // 生成动态菜单
          const roles = flattening(menus)
          console.log(menus,roles,'routes');
          commit('SET_MENU', menus)
          resolve(res)
        }).catch(error => {
          reject(error)
        })
      })
    },

  }
}

export default user
  1. 回到 view /login.vue 页面中 当登录成功之后 就调用这个接口

这个是后端给的接口

这个是登录成功之后 后端返回的数据

我们需要对这个数据进行处理 用于 侧边栏 头部导航 还有动态路由 的配置

因为后端给到的数据不是路由表里面 一一对应的 path name 等键值对的形式,就需要自行处理

json 复制代码
[
    {
        "path": "/home",
        "name": "Home",
        "meta": {
            "title": "首页",
            "noCache": true
        },
        "id": 1
    },
    {
        "path": "/n1",
        "name": "Nested1",
        "meta": {
            "title": "Nested1",
            "noCache": true
        },
        "id": 3,
        "children": [
            {
                "path": "/n1/n2",
                "name": "Nested2",
                "meta": {
                    "title": "Nested2",
                    "noCache": true
                },
                "id": 4
            }
        ]
    },
    {
        "path": "/test",
        "name": "Test",
        "meta": {
            "title": "test",
            "noCache": true
        },
        "id": 2
    }
]

这个时候就存储一下,就可以直接使用了 我们在这里的时候就可以addRoute了,然后在页面中打印

注意

  1. router.addRoute() 添加路由之后,通过router.options.routers 是查看不到添加的动态路由信息 需要使用 router.getRoutes() 可以查看到

  1. 这个时候还没有完,会发现刷新这个就白屏了

正常

刷新

这里需要 去 路由守卫 router.beforeEach 里面去处理

javascript 复制代码
/**
 * 全站权限配置
 *
 */
import router from '@/router'
import store from '@/store'
import Layout from '@/views/Main'
import { getStore, setStore, clearStore, removeStore } from '@/util/storage'
import NProgress from 'nprogress' // progress bar
import 'nprogress/nprogress.css' // progress bar style
NProgress.configure({ showSpinner: false })

/**
 * 导航守卫,相关内容可以参考:
 * https://router.vuejs.org/zh/guide/advanced/navigation-guards.html
 */

// 记录路由
let hasRoles =true
router.beforeEach(async(to, from, next) => {
  NProgress.start()
  // 判断token
  const token = getStore({ name: 'access_token' })
  if (!token && to.name !== 'login') {
    next({ name: 'login' })
    NProgress.done()
  } else if (token && to.name == 'login') {
    // 跳转页面
    next({ path: '/' })
    NProgress.done()
  } else {
    if(token && hasRoles){
      await store.dispatch("GetInfo")
      hasRoles =false
      next({...to,replace:true})
    }else{
      next()
    }
    NProgress.done()
  }

})


router.afterEach(() => {
  NProgress.done()
})

就不会出现白屏问题了,正常刷新正常有

关于 通配符 404页面,我的处理是在动态路由都添加进去之后在了添加 也是在 permission.js 中添加的

tip 可能遇到的问题

如果访问不成功,就需要关注,component 的引入,可能是自己的页面名称没有和它匹配

这里和我们在处理数据的时候,对于component 里面的路径有关的

好了,以上就是我的全部 实现过程,也走了很多弯路,尤其是那个router.options.routers这个打印不出来我的动态路由,我一度迷茫,说addRoute 咋没有效果 失效了呢,惆怅是不是添加进入的时机不对,救命!!!

相关推荐
天下无贼!7 分钟前
2024年最新版Vue3学习笔记
前端·vue.js·笔记·学习·vue
Jiaberrr7 分钟前
JS实现树形结构数据中特定节点及其子节点显示属性设置的技巧(可用于树形节点过滤筛选)
前端·javascript·tree·树形·过滤筛选
赵啸林11 分钟前
npm发布插件超级简单版
前端·npm·node.js
罔闻_spider44 分钟前
爬虫----webpack
前端·爬虫·webpack
吱吱鼠叔1 小时前
MATLAB数据文件读写:1.格式化读写文件
前端·数据库·matlab
爱喝水的小鼠1 小时前
Vue3(一) Vite创建Vue3工程,选项式API与组合式API;setup的使用;Vue中的响应式ref,reactive
前端·javascript·vue.js
WeiShuai1 小时前
vue-cli3使用DllPlugin优化webpack打包性能
前端·javascript
Wandra1 小时前
很全但是超级易懂的border-radius讲解,让你快速回忆和上手
前端
ice___Cpu1 小时前
Linux 基本使用和 web 程序部署 ( 8000 字 Linux 入门 )
linux·运维·前端
JYbill1 小时前
nestjs使用ESM模块化
前端