Vue-Element-Adminのルーターは、常にconstantRoutesとasyncRoutesを使用してルートを定義します。store.modules.permission.jsには、2つの権限のデフォルトの判断方法があり、ナビゲーションガードはpermission.jsで実行されます。ルートディレクトリ内。ロジック;
constantRoutes:ログインページ、404、その他の一般的なページなど、動的な判断権限を必要としないルート。
asyncRoutes:権限を動的に決定し、addRoutesを介して動的に追加する必要があるページ。
1.vue-element-adminでの動的ルーティングの実装
routerフォルダーの下のindex.jsは、プロジェクトの合計ルーティングエントリです。index.jsがモジュールを登録した後、デフォルトでconstantRoutes非特権ルーティングを追加します。store/ modules /permission.jsで静的+動的ルーティング権限を維持します。ルートに保存するディレクトリの下のpermission.jsは、/ router /index.jsにあるナビゲーションガードロジックを実装します。
// router/index.js 部分代码
// 模块化,首先引入在modules目录下需要用的router
import componentsRouter from './modules/components'
import chartsRouter from './modules/charts'
import tableRouter from './modules/table'
import nestedRouter from './modules/nested'
import yzgTest from './modules/yzg'
//constantRoutes 是静态路由,不需要动态权限判断
export const constantRoutes = []
//constantRoutes 是动态路由,需要动态权限判断
export const asyncRoutes = []
//
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
}
export default router
グローバル状態配列はstore / modules / permit.jsで維持されます。これは、現在ログインしているユーザーのメニュー権限を維持し、ガードをルーティングするときの動的ルーティングの切り替えと、store /での状態状態の動的ルーティングを完了します。 modules /permission.jsメンテナンスロジックは次のとおりです。
// 首先,从index.js中引入已经定义过的2个router数组
import { asyncRoutes, constantRoutes } from '@/router'
// 全局变量state,routes和addRoutes数组
const state = {
routes: [],
addRoutes: []
}
// mutations 是唯一可以更改state的函数,使用SET_ROUTES定义更改方法,SET_ROUTES(state, routes)的入参routes赋值给addRoutes数组,将constantRoutes静态路由数组增加routes;
const mutations = {
SET_ROUTES: (state, routes) => {
state.addRoutes = routes
state.routes = constantRoutes.concat(routes)
}
}
// vue中store状态管理,通过actions调用 mutations 中封装的方法来实现对于state更改,
// 这里是vue-element-admin中动态路由的主要判断逻辑发生地方,首先判定用户角色是否包含admin(可能多角色),是则将所有asyncRoutes 加入到constantRoutes,若用户角色没有包含admin,则调用filterAsyncRoutes函数,递归地判定asyncRoutes.roles属性是否有该角色,即是否有权限,将有权限的router赋值accessedRoutes 后加入到constantRoutes;
const actions = {
generateRoutes({ commit }, roles) {
return new Promise(resolve => {
let accessedRoutes
if (roles.includes('admin')) {
accessedRoutes = asyncRoutes || []
} else {
accessedRoutes = filterAsyncRoutes(asyncRoutes, roles)
}
commit('SET_ROUTES', accessedRoutes)
resolve(accessedRoutes)
})
}
}
//-----------------
// 两个上面使用的方法
function hasPermission(roles, route) {
if (route.meta && route.meta.roles) {
return roles.some(role => route.meta.roles.includes(role))
} else {
return true
}
}
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
}
export default {
namespaced: true,
state,
mutations,
actions
}
最後に、ルートディレクトリのpermission.jsにあるルーティングガードロジックを確認します。
// vue-element-admin中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', '/auth-redirect'] // no redirect whitelist
// 路由之前,逻辑判定
router.beforeEach(async(to, from, next) => {
// 开始进度条
NProgress.start()
// set page title
document.title = getPageTitle(to.meta.title)
// determine whether the user has logged in
const hasToken = getToken()
// 有token,如果想去login则调到首页,如果是其他页面先判定是否有角色,有的话就跳过去,没有的话发请求得到永不信息,再调用函数维护store路由列表,报错要么没权限,要么是请求超时,就要返回error,清除token,返回登录页
// 没有token,且不是白名单内的,返回登录页
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 && store.getters.roles.length > 0
if (hasRoles) {
next()
} else {
try {
const { roles } = await store.dispatch('user/getInfo')
const accessRoutes = await store.dispatch('permission/generateRoutes', roles)
router.addRoutes(accessRoutes)
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 {
if (whiteList.indexOf(to.path) !== -1) {
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()
})
AsyncRoutesは意図的にmeta.rolesを使用してロールを定義するため、バックエンドリクエストがユーザーのロールを返した後、判定ロジックをpermission.jsにリンクできます。
2、vueでのルーティング
Vue-routerは、Vue.jsの公式ルーティングプラグインであり、vue.jsと緊密に統合されており、アクセスパスを設定し、パスとコンポーネントをマップするために使用されます。従来のページアプリケーションは、いくつかのハイパーリンクを使用してページを切り替えたりジャンプしたりします。vue-routerシングルページアプリケーションでは、パス間の切り替え、つまりコンポーネントの切り替えです。ルーティングモジュールの本質は、URLとページの間のマッピング関係を確立することです。vue-routerは、単一ページのフロントエンドルーティングを実装する際にハッシュモードと履歴モードを提供します。
router.push(location)= window.history.pushState
別のURLに移動するには、router.pushメソッドを使用します。このメソッドは履歴スタックに新しいレコードを追加するため、ユーザーがブラウザの[戻る]ボタンをクリックすると、前のURLに戻ります。