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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM