当前位置:首页 > 网站技术 > 前端技术 > 正文内容

vue-element-admin框架之动态路由配置及思路(个人实践,拒绝照搬)

小彬2021-02-28前端技术455

思路:三步

1、在路由拦截前对路由数据进行存储和处理

2、在渲染路由的router里合并constRoutes和asyncRoutes

3、在权限进行修改的时候进行存储和更新路由数据

4、对后端返回的数据进行处理和返回的数据案例

5、补充针对路由获取的异常处理

vue-element-admin框架之动态路由配置及思路(个人实践,拒绝照搬)


vue-element-admin默认是对admin和editor两个角色进行权限处理

但是在实际项目中,不止两个角色,所以本项目是通过拿取登录token值请求后端接口返回的路由数据进行处理

1、在路由拦截前对路由数据进行获取和处理

我是在登录的时候进行数据存储,然后在路由拦截的时候把处理后的路由添加到路由上router.addRoutes(accessRouter)

vue-elemen-admin框架是在vuex进行路由数据处理和存储的

src/store/modules/permission.js

import { getAsyncRoutes } from '@/utils/menu'
const actions = {
  generateRoutes({ commit }, roles) {
    return new Promise(resolve => {
      let accessedRoutes
      let new_rou=JSON.parse(localStorage.getItem('routers'))
      const asyncRoutes = getAsyncRoutes(new_rou)
      console.log(asyncRoutes,'修改')
      if (roles.includes('admin')) {
        accessedRoutes = asyncRoutes || []
      } else {
        accessedRoutes = filterAsyncRoutes(asyncRoutes, roles)
      }
      commit('SET_ROUTES', accessedRoutes)
      resolve(accessedRoutes)
    })
  }
}

注意:由于JSON.stringify不能对函数进行转换,所以我存储的时候是对接口返回的数据进行存取,在渲染之前才对数据进行处理

由于我路由使用的是localStroage进行存取,所以vuex里的方法可以删除,影响不大。

主要是因为使用vuex时在页面进行刷新的时候会失效,导致路由报404,故我使用的是localStroage

src/views/login

handleLogin() {
      this.$refs.loginForm.validate(valid => {
        if (valid) {
          this.loading = true
          this.$store.dispatch('user/login', this.loginForm)
            .then(() => {
              manageMenusUserTree().then(response => {
                const data = response.data
                console.log(data,'登录请求的')
                localStorage.setItem('routers',JSON.stringify(data))
                this.$router.push({ path: this.redirect || '/', query: this.otherQuery })
                this.loading = false
              })
            })
            .catch(() => {
              this.loading = false
            })
        } else {
          console.log('error submit!!')
          return false
        }
      })
    },


路由拦截之前的路由添加

src/permission.js
import { getAsyncRoutes } from '@/utils/menu'

  const { roles } = await store.dispatch('user/getInfo')
  //使用vuex时,通过异步拿到路由数据
  // const accessRoutes = await store.dispatch('permission/generateRoutes', roles)
  
  //使用localStorage时,通过localStorage读取拿取路由数据   所以我用的是下面这个方法。
  const accessRoutes=getAsyncRoutes(JSON.parse(localStorage.getItem('routers')))
  console.log(accessRoutes,'add到页面的路由')

  //重要一步
  router.addRoutes(accessRoutes)

2、在渲染路由的router里合并constRoutes和asyncRoutes

注:我看过好多文章,都没标注这里,我在这耽误许久。如果不对路由进行合并,页面是打不开的,而且还不报错。

src/router/index.js
import { getAsyncRoutes } from '@/utils/menu'

var asyncRoutes=[]
if(localStorage.getItem('routers')){
  let new_rou=JSON.parse(localStorage.getItem('routers'))
  asyncRoutes = getAsyncRoutes(new_rou)
}
console.log(asyncRoutes,'动态路由')

const createRouter = () => new Router({
  mode: 'history',
  scrollBehavior: () => ({ y: 0 }),
  routes: constantRoutes.concat(asyncRoutes)
})


3、在权限进行修改的时候进行存储和更新路由数据

src/views/manage/menu.vue

  async getRoutes() {
    const res = await manageMenusTree()
    console.log('获取路路由', res)
    this.rolesList = res.data;
    
    localStorage.setItem('routers',JSON.stringify(res.data))
  },
  //添加路由
  async addList(val, type) {
      for (var i in val) {
        this.addArrs[i] = val[i]
      }
      if (type === 'add') {
        await manageMenusAdd(this.addArrs)
      } else {
        await manageMenusEdit(this.addArrs.id, this.addArrs)
      }
      this.$alert(this.addUserTitle === 'add' ? '添加权限成功!' : '修改权限成功!', '提交', {
        confirmButtonText: '确定',
        type: 'success',
        callback: action => {
          this.$router.go(0)
        }
      })
      //页面数据更新
      this.getRoutes()
    },


左侧导航的路由渲染

如果不渲染,左侧是没有导航的

src/layout/components/Sidebar/index.vue

import { getAsyncRoutes } from '@/utils/menu'

routers() {
  const newRouter=getAsyncRoutes(JSON.parse(localStorage.getItem('routers')))
  return newRouter
}


4、对路由数据的处理和后端返回的数据案例

这一步异常重要,我写在最后是因为前几步是思路。

我参考过很多方法,因为在对component进行赋值的时候,要考虑到异步引入组件或者同步引入组件

而且同步引入组件和异步引入组件有很大的区别,vue-element-admin文档也做了详细的说明

https://panjiachen.gitee.io/vue-element-admin-site/zh/guide/essentials/permission.html

const map={
 login:require('login/index').default // 同步的方式
 login:()=>import('login/index')      // 异步的方式
 }
 //你存在服务端的map类似于
 const serviceMap=[
 { 
 path: '/login', 
 component: 'login', 
 hidden: true 
 }]
 //之后遍历这个map,动态生成asyncRoutes并将 component 替换为 map[component]


我使用的后端数据和element-admin不一样,所以在对数据处理的时候也独具一格。

src/utils/menu.js

/* Layout */
import Layout from '@/layout'
export function getAsyncRoutes(routes) {
  const res = []
  const keys = ['path', 'name', 'children', 'redirect', 'alwaysShow', 'title','icon']
  routes.forEach(item => {
    const newItem = {}
      if (item.children) {
        newItem.component = Layout
      } else {
        newItem.component =(resolve)=>require([`@/views${item.component}.vue`],resolve)
      }
    for (const key in item) {
      if (keys.includes(key)) {
        newItem[key] = item[key]
        if(item.children){
          newItem.alwaysShow = true
          newItem.children =item.children
        }
      }
    }
    if (newItem.children && newItem.children.length >0) {
      newItem.children = getAsyncRoutes(item.children)
    }
    res.push(newItem)
  })
  return res
}


后端数据示例:

[{
    "id": 1,
    "name": "后台管理",
    "code": "001",
    "path": "/manage",
    "component": "/manage",
    "hidden": true,
    "title": "后台管理",
    "icon": "dashboard",
    "children": [{
      "id": 14,
      "name": "用户管理",
      "code": "001001",
      "path": "/manage/user",
      "component": "/manage/user",
      "hidden": true,
      "title": "用户管理",
      "icon": "user"
    }, {
      "id": 15,
      "name": "角色管理",
      "code": "001002",
      "path": "/manage/role",
      "component": "/manage/role",
      "hidden": true,
      "title": "角色管理",
      "icon": "tree-table"
    }, {
      "id": 2008,
      "name": "菜单权限管理",
      "code": "001003",
      "path": "/manage/menu",
      "component": "/manage/menu",
      "hidden": true,
      "title": "菜单权限管理",
      "icon": "nested"
    }]
  },,,,]


5、补充针对路由获取的异常处理

主要是针对在没有路由的时候应该进行登录操作,只有在路由存在的情况下才能跳转到首页

let rouStorage=localStorage.getItem('routers')
          if( rouStorage != 'undefined' && rouStorage != null){
            console.warn('permisson.js error')
            accessRoutes=getAsyncRoutes(JSON.parse(rouStorage))
          }else{
            accessRoutes = await store.dispatch('permission/generateRoutes', roles)
          }


标签: vue
分享给朋友:

相关文章

HTTP之协议结构、通讯原理以及http特性和使用方法

HTTP之协议结构、通讯原理以及http特性和使用方法

1、http协议 超文本传输协议(http)是一种通信协议,它允许将超文本标记语言(html)文档从web服务器传送到客户端的浏览器http是一个属于应用层的面向对象的协议web是一种基于超...

PC端固定顶部的导航栏在屏幕缩小时左右滚动

PC端固定顶部的导航栏在屏幕缩小时左右滚动

一般网站都会有固定导航栏,但是大多数都是随着屏幕的缩小并不会出现左右滚动。比如京东和淘宝的官网就是没有出现左右滚动你想想,如果把这个问题解决掉,其实你比他们还优秀言归正传,那就来说说怎么实现。首先上我...

浏览器几种缓存方法的比较

浏览器几种缓存方法的比较

在Web应用领域,Web缓存大致可以分为以下几种类型:1.数据库数据缓存Web应用,特别是社交网络服务类型的应用,往往关系比较复杂,数据库表繁多,如果频繁进行数据库查询,很容易导致数据库不堪重荷。为了...

Vue2.x 实战总结知识点

Vue2.x 实战总结知识点

1、git操作上传文件到gitee 先在线上建一个仓库bin012,然后本地打开git bash执行以下三步  mkdir bin012  cd&...

使用宝塔Linux部署node项目+前端包上线

使用宝塔Linux部署node项目+前端包上线

使用宝塔搭建项目还是非常便捷的1、进入软件商店下载PM2,然后可以设置放置到首页2、上传node包到宝塔把本地的node包压缩好上传到特定的目录下,node_modules 不用打包。特定的目录:根据...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

分享:

支付宝

微信