Vue 动态路由的实现(后台传递路由,前端拿到并生成侧边栏)

需求:后台传来当前用户对应权限的路由表,前端通过调接口拿到后处理(后端处理路由)

思路

1.后台同学返回一个json格式的路由表,我用easymock造了一段:动态路由表,大家可参考;
2.因为后端同学传回来的都是字符串格式的,但是前端这里需要的是一个组件对象啊,写个方法遍历一下,将字符串转换为组件对象;
3.利用vue-router的beforeEach、addRoutes、localStorage来配合上边两步实现效果;
4.左侧菜单栏根据拿到转换好的路由列表进行展示;
大体步骤:拦截路由->后台取到路由->保存路由到localStorage(用户登录进来只会从后台取一次,其余都从本地取,所以用户,只有退出在登录路由才会更新)

代码

从easymock造的一段动态路由表

"data": {
    "router": [
      {
        "path": "",
        "component": "Layout",
        "redirect": "dashboard",
        "children": [
          {
            "path": "dashboard",
            "component": "dashboard/index",
            "meta": {
              "title": "首页",
              "icon": "dashboard"
            }
          }
        ]
      },
      {
        "path": "/example",
        "component": "Layout",
        "redirect": "/example/table",
        "name": "Example",
        "meta": {
          "title": "案例",
          "icon": "example"
        },
        "children": [
          {
            "path": "table",
            "name": "Table",
            "component": "table/index",
            "meta": {
              "title": "表格",
              "icon": "table"
            }
          },
          {
            "path": "tree",
            "name": "Tree",
            "component": "tree/index",
            "meta": {
              "title": "树形菜单",
              "icon": "tree"
            }
          }
        ]
      },
      {
        "path": "/form",
        "component": "Layout",
        "children": [
          {
            "path": "index",
            "name": "Form",
            "component": "form/index",
            "meta": {
              "title": "表单",
              "icon": "form"
            }
          }
        ]
      },
      {
        "path": "*",
        "redirect": "/404",
        "hidden": true
      }
    ]
  }

router/index.js

//清空路由表
export const asyncRouterMap = []

src/permission.js

import axios from 'axios'
const _import = require('./router/_import_' + process.env.NODE_ENV)//获取组件的方法
import Layout from '@/views/layout/Layout' //Layout 是架构组件,不在后台返回,在文件里单独引入
var getRouter;
router.beforeEach((to, from, next) => {
if (!getRouter) {//不加这个判断,路由会陷入死循环
    if (!getObjArr('router')) {
      axios.get('https://www.easy-mock.com/mock/5c70ba7331b3fb6533b94241/example/restful/:id/list').then(res => {
        getRouter = res.data.data.router//后台拿到路由
        saveObjArr('router', getRouter) //存储路由到localStorage

        routerGo(to, next)//执行路由跳转方法
      })
    } else {//从localStorage拿到了路由
      getRouter = getObjArr('router')//拿到路由
      routerGo(to, next)
    }
  } else {
    next()
  }
}
function routerGo(to, next) {
  getRouter = filterAsyncRouter(getRouter) //过滤路由
  router.options.routes = getRouter;//必须在addroutes前,使用router.options.routes=XXXXX的方法手动添加
  router.addRoutes(getRouter) //动态添加路由
  global.antRouter = getRouter //将路由数据传递给全局变量,做侧边栏菜单渲染工作
  next({ ...to, replace: true })
}

function saveObjArr(name, data) { //localStorage 存储数组对象的方法
  localStorage.setItem(name, JSON.stringify(data))
}

function getObjArr(name) { //localStorage 获取数组对象的方法
  return JSON.parse(window.localStorage.getItem(name));

}

function filterAsyncRouter(asyncRouterMap) { //遍历后台传来的路由字符串,转换为组件对象
  const accessedRouters = asyncRouterMap.filter(route => {
    if (route.component) {
      if (route.component === 'Layout') {//Layout组件特殊处理
        route.component = Layout
      } else {
        route.component = _import(route.component)
      }
    }
    if (route.children && route.children.length) {
      route.children = filterAsyncRouter(route.children)
    }
    return true
  })

  return accessedRouters
}

新增两个js
router/_import_production

module.exports = file => () => import('@/views/' + file + '.vue')

router/_import_development

module.exports = file => require('@/views/' + file + '.vue').default // vue-loader at least v13.0.0+

动态路由基本完成!
参考地址:https://segmentfault.com/a/1190000015419713

你可能感兴趣的:(web)