element-ui 动态路由

很多时候,需要动态加载路由,来控制权限。

基于element ui 得动态路由写法

1.设置不需要权限的路由constantRoutes和需要判断权限的路由asyncRoutes ,动态过滤需要判断权限的路由,并通过addRoutes添加路由

router/index,js

/*
 * @Descripttion: 
 * @Version: 
 * @Date: 2021-06-11 13:58:03
 */

import Vue from 'vue'
import Router from 'vue-router'


Vue.use(Router)

/* Layout */
import Layout from '@/layout'

/**
 * constantRoutes
 * a base page that does not have permission requirements
 * all roles can be accessed
 */
// 这里放着不需要判断权限的路由
export const constantRoutes = [{
    path: '/login',
    component: () => import('@/views/login/index'),
    hidden: true
  },

  //  作品评审
  {
    path: '/theme',
    redirect: '/theme/list',
    name: 'theme',
    component: Layout,
    meta: {
      title: '作品评审',
      icon: 'dashboard',
    },
    children: [{
        meta: {
          title: '作品评审',
          icon: 'dashboard',

        },
        name: 'themelist',
        path: 'list',
        component: () => import('@/views/theme/list'),
      },
      {
        meta: {
          title: '作品评审',
          icon: 'dashboard',
          activeMenu: '/theme/list'
        },
        name: 'themeadd',
        hidden: true,
        path: 'add',
        component: () => import('@/views/theme/add'),
      },
    ]
  },

]
// 需要判断权限的路由
export const asyncRoutes = [{
  path: '/',
  redirect: '/list',
  name: 'dat',
  component: Layout,
  meta: {
    title: '数据管理',
    icon: 'example',
    // 区分权限得标识
    roles: ["管理员"]
  },
  children: [{
      meta: {
        title: '数据管理',
        icon: 'example'
      },
      path: 'list',
      name: 'manageList',
      component: () => import('@/views/area/list.vue'),

    },
    {
      meta: {
        title: '数据管理',
        icon: 'example',
        activeMenu: '/list'
      },
      path: 'add',
      name: 'manageAdd',
      component: () => import('@/views/area/add.vue'),
      hidden: true
    },
  ]
},
// 账号管理
{
  path: '/tag',
  redirect: '/tag/list',
  name: 'tag',
  component: Layout,
  meta: {
    title: '账号管理',
    icon: 'example',
     // 区分权限得标识
    roles: ["管理员"]
  },
  children: [{
      meta: {
        title: '账号管理',
        icon: 'example'
      },
      path: 'list',
      name: 'taglist',
      component: () => import('@/views/tag/list.vue'),
    },
    {
      meta: {
        title: '账号管理',
        icon: 'example',
        activeMenu: '/tag/list'
      },
      path: 'add',
      name: 'tagadd',
      component: () => import('@/views/tag/add.vue'),
      hidden: true
    },

  ]
},


{
  path: '*',
  redirect: '/404',
  hidden: true
}

]



const createRouter = () => new Router({
  // mode: 'history', // require service support
  scrollBehavior: () => ({
    y: 0
  }),
  routes: constantRoutes
})

const router = createRouter()

// Detail see: https://github.com/vuejs/vue-router/issues/1234#issuecomment-357941465
export function resetRouter() {
  const newRouter = createRouter()
  router.matcher = newRouter.matcher // reset router
}
router.beforeEach((to, from, next) => {
  if (to.path === '/login') {
    next();
  } else {
    let token = localStorage.getItem('Authorization');
    if (token === 'null' || token === '') {
      next('/login');
  
    } else {
      next();
    }
  }
});
export default router

  登录login.vue

 this.$store.dispatch("user/login", this.loginForm)

store中user模块 store/modules/user.js

import {
  login,
  logout,
  getInfo
} from '@/api/user'
import {
  getToken,
  setToken,
  removeToken
} from '@/utils/auth'
import router, {
  resetRouter
} from '@/router'

const state = {
  token: getToken(),
  name: '',
  avatar: '',
  introduction: '',
  roles: ""
}

const mutations = {
  SET_TOKEN: (state, token) => {
    state.token = token
  },
  SET_INTRODUCTION: (state, introduction) => {
    state.introduction = introduction
  },
  SET_NAME: (state, name) => {
    state.name = name
  },
  SET_AVATAR: (state, avatar) => {
    state.avatar = avatar
  },
  SET_ROLES: (state, roles) => {
    state.roles = roles
  }
}

const actions = {
  // 登录
  login({
    commit
  }, userInfo) {
    const {
      username,
      password
    } = userInfo
    return new Promise((resolve, reject) => {
       // 数据结构
      //  var res={
      //   token:"123",
      //   username:"123",
      //   role:"管理员"
      // }
 
    //  调用登录方法 走接口
      login({
        username: username.trim(),
        password: password
      }).then(response => {
        console.log(response)
        var res = response.data;
        // 登录成功后将token存储在cookie之中
        setToken(res.token)
        sessionStorage.setItem('username', res.username)
        sessionStorage.setItem('role', res.role)
        sessionStorage.setItem('id', res.id)

        commit('SET_NAME', res.username)
        commit('SET_TOKEN', res.token)
        // commit('SET_ROLES', res.role)

        // commit('SET_ROLES', response.data.role)
        resolve()
      }).catch(error => {
        reject(error)
      })
    })
  },
  // 设置角色
  setRole({
    commit
  }, role) {
    commit('SET_ROLES', role)
  },
  // 等处登录
  logout({
    commit,
    state,
    dispatch
  }) {
    return new Promise((resolve, reject) => {
      logout(state.token).then(() => {
        commit('SET_TOKEN', '')
        commit('SET_ROLES', "")
        removeToken()
        resetRouter()

        // reset visited views and cached views
        // to fixed https://github.com/PanJiaChen/vue-element-admin/issues/2485
        dispatch('tagsView/delAllViews', null, {
          root: true
        })

        resolve()
      }).catch(error => {
        reject(error)
      })
    })
  },

  // 移除token
  resetToken({
    commit
  }) {
    return new Promise(resolve => {
      commit('SET_TOKEN', '')
      commit('SET_ROLES', "")
      removeToken()
      resolve()
    })
  },
}

export default {
  namespaced: true,
  state,
  mutations,
  actions
}

 store/modules/permission.js  过滤动态路由,

/*
 * @Descripttion: 
 * @Version: 1.0.1
 * @Date: 2021-06-11 13:58:03
 */
import {
  constantRoutes,
  asyncRoutes
} from '@/router'

/**
 * 使用meta.role确定当前用户是否具有权限
 * @param roles
 * @param route
 */
function hasPermission(roles, route) {
  if (route.meta && route.meta.roles) {
    return roles.some(role => route.meta.roles.includes(role))
  } else {
    return true
  }
}

/**
 * 递归过滤异步路由表
 * @param routes asyncRoutes
 * @param roles
 */
export function filterAsyncRoutes(routes, roles) {
  console.log(routes, roles)
  const res = []
  routes.forEach(route => {
    const tmp = {
      ...route
    }
    if (hasPermission(roles, tmp)) {
      if (tmp.children) {
        tmp.children = filterAsyncRoutes(tmp.children, roles)
      }
      res.push(tmp)
    }
  })

  return res
}

const state = {
  routes: [],
  addRoutes: []
}

const mutations = {
  SET_ROUTES: (state, routes) => {
    state.addRoutes = routes;

    state.routes = constantRoutes.concat(routes);
    console.log(state.routes)
  }
}

const actions = {
  generateRoutes({
    commit
  }, roles) {
    
    return new Promise(resolve => {
      let accessedRoutes;
      // 管理员是最高权限,所有路由均可访问得情况下 就把注释放出来
      // if (roles.includes('管理员')) {
      //   accessedRoutes = asyncRoutes || []
      // } else {
        // 获取符合条件的需要添加的动态路由
        accessedRoutes = filterAsyncRoutes(asyncRoutes, roles)
      // }
     
      commit('SET_ROUTES', accessedRoutes)
      resolve(accessedRoutes)
    })
  }
}

export default {
  namespaced: true,
  state,
  mutations,
  actions
}
View Code

全局路由守卫 permission.js

/*
 * @Descripttion: 
 * @Version: 1.0.1
 * @Date: 2021-06-11 13:58:03
 */
import router from './router'
import store from './store'
import {
  Message
} from 'element-ui'
import NProgress from 'nprogress' // progress bar
import 'nprogress/nprogress.css' // progress bar style
import {
  getToken
} from '@/utils/auth' // get token from cookie
import getPageTitle from '@/utils/get-page-title'

NProgress.configure({
  showSpinner: false
}) // NProgress Configuration



router.beforeEach(async (to, from, next) => {
  // start progress bar
  NProgress.start()

  // set page title
  document.title = getPageTitle(to.meta.title)

  // determine whether the user has logged in
  const hasToken = getToken()
 
  if (hasToken) {
    if (to.path === '/login') {
      // if is logged in, redirect to the home page
      next({
        path: '/'
      })
      NProgress.done() // hack: https://github.com/PanJiaChen/vue-element-admin/pull/2939
    } else {
      // determine whether the user has obtained his permission roles through getInfo
      const hasRoles = store.getters.roles
      if (hasRoles) {
        next()
      } else {
        try {
          
          // 登陆以后获取到用户角色,用来判断权限
          const roles = sessionStorage.getItem('role')
          // 写入角色
          store.dispatch('user/setRole', roles)
    
          // 获取需要动态添加得路由
          const accessRoutes = await store.dispatch('permission/generateRoutes', [roles])
       
          router.options.routes = store.getters.routes;
          // 动态添加可访问路由
          router.addRoutes(accessRoutes)
          //hack方法以确保addRoutes是完整的
          //设置replace:true,这样导航就不会留下历史记录
          next({
            ...to,
            replace: true
          })
        } catch (error) {
          
          // 删除token并转到登录页以重新登录
          await store.dispatch('user/resetToken')
          Message.error(error || 'Has Error')
          next(`/login?redirect=${to.path}`)
          NProgress.done()
        }
      }
    }
  } else {
      //  这里可以设置白名单 ,不需要判断得路由导航,例如注册,登录等,可以用数组,可以直接比较
    if (to.path.includes('login')) {
      next()
    } else {
      // 没有访问权限的其他页将重定向到登录页
      next(`/login?redirect=${to.path}`)
      NProgress.done()
    }
  }
})

router.afterEach(() => {
  // finish progress bar
  NProgress.done()
})
View Code
原文地址:https://www.cnblogs.com/GoTing/p/15036455.html