Ant design pro of vue 启动流程分析
在开发模式下,程序的入口应该是 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就已经开始在工作了,登录之后又在获取所有的路由表,从而能够在我们访问不同的连接的时候,进入不同的页面.