在開發模式下,程序的入口應該是 src/main.js,其中關鍵的代碼
// 這個router對原始router進行了hack注入,方便在開始或結束后調用相應代碼,具體實現
// 可以到相應目錄查看 這種寫法其實是引入 當前目錄同級目錄router目錄中引入 index.js
import router from './router' new Vue({ router, store, created: bootstrap, render: h => h(App) }).$mount('#app')
可以看到在此初始化了一個vue的實例,大致的意思就是把router和store渲染到App中去。接下來渲染的話就進入到了src/app.vue文件中了
<template> <a-locale-provider :locale="locale"> <div id="app"> <router-view/> </div> </a-locale-provider> </template>
可以看到,在模版中只是渲染了router-view組件,而這個router-view就告訴了,Vue Router 在哪里渲染它們。
這樣的話,我們的頁面就會根據不同的路由進行不同頁面的渲染了。
而渲染的內容是實例化的router中的routes屬性的值,在 /src/router/index.js中有
import Vue from 'vue' import Router from 'vue-router' import { constantRouterMap } from '@/config/router.config' // 一般代表 src/config/router.config.js // hack router push callback const originalPush = Router.prototype.push Router.prototype.push = function push (location, onResolve, onReject) { if (onResolve || onReject) return originalPush.call(this, location, onResolve, onReject) return originalPush.call(this, location).catch(err => err) } Vue.use(Router) export default new Router({ mode: 'history', base: process.env.BASE_URL, scrollBehavior: () => ({ y: 0 }), routes: constantRouterMap }) 所以會渲染constantRouterMap具體內容如下: import { UserLayout, BlankLayout } from '@/layouts' export const constantRouterMap = [ { path: '/user', component: UserLayout, redirect: '/user/login', hidden: true, children: [ { path: 'login', name: 'login', component: () => import(/* webpackChunkName: "user" */ '@/views/user/Login') }, ...................... ]
可以看到這其中就包含了我們的登錄頁面。如果用戶此時未登錄的話,就會進入登錄界面。至於登錄的流程大家可以看我另一篇文章。在登錄成功之后會有如下代碼
this.$router.push({ path: '/' })
這是router的導航方式。push的話可以理解為導航至 / ,具體是什么意思大家參考官方文檔。至此我們就進入了項目首頁。之前我們有提到過,項目中使用的router是經過hack之后的,所以在router每次操作時其實都會做檢查工作,實現的代碼在
src/permission.js中,代碼如下:
router.beforeEach((to, from, next) => { NProgress.start() // start progress bar進度條相關 if (Vue.ls.get(ACCESS_TOKEN)) { // 通過token判斷是否登錄 /* 已經登錄並且訪問的頁面是登錄路由的話則跳轉到指定連接 */ if (to.path === '/user/login') { next({ path: '/dashboard/workplace' }) NProgress.done() } else { // 如果不是訪問的登錄頁面,則會去獲取角色 role(和動態路由有關的值) // 如果不存在角色 if (store.getters.roles.length === 0) { // 則去獲取角色, store和vuex有關,有需要的同志自行查找 store.dispatch('GetInfo') .then(res => { // 獲取角色之后 const roles = res.result && res.result.role // 下面的代碼是說 從后端獲取用戶的路由菜單,動態添加可訪問路由表 // 我的代碼已經改成了后端獲取方式,不同的代碼可能稍有不同 store.dispatch('GenerateRoutes', { roles }).then(() => { // 把已獲取到的路由菜單加入到路由表中 router.addRoutes(store.getters.addRouters) const redirect = decodeURIComponent(from.query.redirect || to.path) if (to.path === redirect) { // hack方法 確保addRoutes已完成 ,set the replace: true so the navigation will not leave a history record next({ ...to, replace: true }) } else { // 跳轉到目的路由 next({ path: redirect }) } }) }) .catch(() => { notification.error({ message: '錯誤', description: '請求用戶信息失敗,請重試' }) store.dispatch('Logout').then(() => { next({ path: '/user/login', query: { redirect: to.fullPath } }) }) }) } else { next() } } } else { if (whiteList.includes(to.name)) { // 在免登錄白名單,直接進入 next() } else { // 導航至登錄頁 next({ path: '/user/login', query: { redirect: to.fullPath } }) NProgress.done() // if current page is login will not trigger afterEach hook, so manually handle it } } })
通過上述代碼解釋,大家應該也知道了,在我們登錄操作之前,其實router就已經開始在工作了,登錄之后又在獲取所有的路由表,從而能夠在我們訪問不同的連接的時候,進入不同的頁面.
