vue element 动态路由配置

本文介绍了如何在Vue.js应用中实现动态路由配置,包括在`src/router/index.js`中定义公共路由,以及在`src/store/modules/permission.js`中获取并处理动态路由。同时,通过`src/permission.js`设置路由拦截器,根据用户权限过滤和添加路由。整个流程涉及到用户登录状态检查、动态添加路由和页面权限控制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

第一步:src/router/index.js 公共路由定义

import Vue from 'vue'
import Router from 'vue-router'
Vue.use(Router)
/* Layout */
import Layout from '@/layout'
export const constantRoutes = [{
        path: '/login',
        component: () =>
            import ('@/views/login/index'),
        hidden: true
    },
    {
        path: '/',
        hidden: true,
        component: Layout,
        redirect: '/dashboard',
        meta: { role: '/menu' },
        children: [{
            path: 'dashboard',
            name: '首页',
            component: () =>
                import ('@/views/dashboard/index'),
            meta: { title: '首页', icon: 'dashboard', role: '/menu', affix: true }
        }]
    },
    {
      path: '/404',
      component: () =>
          import ('@/views/404'),
      hidden: true
    },
]
const createRouter = () => new Router({
    // mode: 'history', // require service support
    scrollBehavior: () => ({ y: 0 }),
    routes: constantRoutes
})
const router = createRouter()
export function resetRouter() {
    const newRouter = createRouter()
    router.matcher = newRouter.matcher // reset router
}
export default router

第二步:src/store/modules/permission.js
获取动态路由、和构造。

import { constantRoutes } from '@/router'
import store from '@/store'
import { getRouter } from '@/api/user' // 获取路由的接口方法
import Layout from '@/layout'
import { MessageBox, Message } from 'element-ui'

function hasPermission(roles, route) {
  if (route.meta && route.meta.roles) {
    return roles.some(role => route.meta.roles.includes(role))
  } else {
    return true
  }
}
const mutations = {
  SET_ROUTES: (state, routes) => {
    state.addRoutes = routes
    state.routes = constantRoutes.concat(routes) //动态路由与和镜态公共路由结合
    // console.log('state.routes',state.routes)
  }
}
/**
 * 把后台返回菜单组装成routes要求的格式
 * @param {*} routes
 */
export function getAsyncRoutes(routes) {
  const res = []
  const keys = ['path', 'name', 'children', 'redirect','meta', 'hidden']
  routes.forEach(item => {
    const newItem = {}
    if (item.component) {
      if (item.component === 'Layout') {
        newItem.component = Layout
      } else {
        newItem.component = loadView(item.component);
      }
    }
    for (const key in item) {
      if (keys.includes(key)) {
        newItem[key] = item[key]
      }
    }
    if (newItem.children && newItem.children.length) {
      newItem.children = getAsyncRoutes(item.children)
    }
    res.push(newItem)
  })
  return res
}
export const loadView = (view) => {
  return (resolve) => require([`@/views${view}`], resolve)
}
export function filterAsyncRoutes(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 actions = {
  generateRoutes({ commit }, roles) {
    return new Promise(async resolve => {
      let accessedRoutes
      // 请求接口 获取动态路由
      const routes = await getRouter() // 获取到动态路由接口
      if(routes.code == 200){
        if(routes.data.length > 0){
          const asyncRoutes = getAsyncRoutes(routes.data) // 对路由格式进行处理
          accessedRoutes = asyncRoutes
          commit('SET_ROUTES', asyncRoutes)
          resolve(accessedRoutes)
        }else{
          MessageBox.confirm('暂无菜单', '暂无菜单', {
              confirmButtonText: '重新登录',
              cancelButtonText: '取消',
              type: 'warning'
          }).then(() => {
              store.dispatch('user/resetToken').then(() => {
                  location.reload()
              })
          })
        }
      }else{
        console.log('过期')
        MessageBox.confirm('是否重新登录?', '当前无登录用户信息', {
            confirmButtonText: '重新登录',
            cancelButtonText: '取消',
            type: 'warning'
        }).then(() => {
            store.dispatch('user/resetToken').then(() => {
                location.reload()
            })
        })
      }
    })
  }
}

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


第三步:src/permission.js 在拦截器中调用


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
const whiteList = ['/login'] // no redirect whitelist
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()
    } else {
    //判断获取来的动态路由的数据是否有数据
      const hasGetUserInfo = store.getters.roles && store.getters.roles.length > 0
      if (hasGetUserInfo) {
        next()
      } else {
        try {
          // get user info
          // await store.dispatch('user/getInfo')
          //调用获取动态的接口
          const {data} = await store.dispatch('user/getInfo')
          // 在这里获取异步路由
          const accessRoutes = await store.dispatch('permission/generateRoutes', data)
          // 调用router.addRoutes方法,将异步路由添加进去
          router.addRoutes(accessRoutes)
          // 在这动态添加最后的通配路由,确保先有动态路由、再有通配路由,解决动态路由刷新会跳转到404问题
          let lastRou = [{ path: '*', redirect: '/404' }]
          router.addRoutes(lastRou)
          next({ ...to, replace: true })
        } catch (error) {
          // remove token and go to login page to re-login
          await store.dispatch('user/resetToken')
          Message.error(error || 'Has Error')
          next(`/login?redirect=${to.path}`)
          NProgress.done()
        }
      }
    }
  } else {
    /* has no token*/
    if (whiteList.indexOf(to.path) !== -1) {
      // in the free login whitelist, go directly
      next()
    } else {
      // other pages that do not have permission to access are redirected to the login page.
      next(`/login?redirect=${to.path}`)
      NProgress.done()
    }
  }
})

router.afterEach(() => {
  // finish progress bar
  NProgress.done()
})



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值