在看完整个项目的目录结构以后,决定从三个主文件入手,也就是先研究App.vue、bootstrap.js、main.js这三个文件。
main.js
main的源码,根据自己的理解新加了一些注释
import Vue from 'vue'
import App from './App.vue'
import {initRouter} from './router' //初始化路由
import './theme/index.less'
import Antd from 'ant-design-vue'
import Viser from 'viser-vue' //引入antv-g2绘制图形
import '@/mock'
import store from './store'
import 'animate.css/source/animate.css' //引入动画样式
import Plugins from '@/plugins'
import {initI18n} from '@/utils/i18n' //引入国际化
import bootstrap from '@/bootstrap' //引入应用启动引导js 和bootstrapUI没关系 =_=|||
import 'moment/locale/zh-cn'
const router = initRouter(store.state.setting.asyncRoutes) //加载路由,异步||非异步。这里结合router中的initRouter函数看看都做了哪些事。
const i18n = initI18n('CN', 'US')
Vue.use(Antd)
Vue.config.productionTip = false
Vue.use(Viser)
Vue.use(Plugins)
bootstrap({router, store, i18n, message: Vue.prototype.$message}) //初始化路由以及路由守卫、axios拦截器。下面会详细说明。
new Vue({
router,
store,
i18n,
render: h => h(App),
}).$mount('#app')
初始化路由相关
- router/index.js 这个文件向外暴露了两个对象loginIgnore, initRouter,分别看看这两个做了什么。
- loginIgnore
// 不需要登录拦截的路由配置
const loginIgnore = {
names: ['404', '403'], //根据路由名称匹配
paths: ['/login'], //根据路由fullPath匹配
/**
* 判断路由是否包含在该配置中
* @param route vue-router 的 route 对象
* @returns {boolean}
*/
includes(route) {
return this.names.includes(route.name) || this.paths.includes(route.path)
}
}
- initRouter
/**
* 初始化路由实例
* @param isAsync 是否异步路由模式
* @returns {VueRouter}
*/
function initRouter(isAsync) {
//首先判断要加载的路由是否为异步路由。传入的参数store.state.setting.asyncRoutes,在配置项中直接修改要加载的是否为异步路由。
//根据判断结果去两个文件下引入不同的配置。
const options = isAsync ? require('./async/config.async').default : require('./config').default
formatRoutes(options.routes) //此方法格式化路由 如果路由路径前没有/并且不是*那就给加上/
// 如果想要配置router的其他配置项,可以在这里直接配置。如:想要切换路由模式为history模式
options.mode = 'history'
return new Router(options) //创建router实例,并传入路由配置。
}
export {loginIgnore, initRouter}
加载路由的流程:
- main.js 中initRouter()判断是异步路由还有同步路由,并且把对应的路由配置项传入,之后返回一个router路由器
- main.js中bootstarp() 将router作为参数传入
- loadRoutes() 中,这块没看懂保存在本地的意义是啥。。。。
// 如果 routesConfig 有值,则更新到本地,否则从本地获取
if (routesConfig) {
store.commit('account/setRoutesConfig', routesConfig)
} else {
routesConfig = store.getters['account/routesConfig']
}
// store/mutation中用到的函数
setRoutesConfig(state, routesConfig) {
state.routesConfig = routesConfig
localStorage.setItem(process.env.VUE_APP_ROUTES_KEY, JSON.stringify(routesConfig))
}
// store/getters中用到的
routesConfig: state => {
if (!state.routesConfig) {
try {
const routesConfig = localStorage.getItem(process.env.VUE_APP_ROUTES_KEY)
state.routesConfig = JSON.parse(routesConfig)
state.routesConfig = state.routesConfig ? state.routesConfig : []
} catch (e) {
console.error(e.message)
}
}
return state.routesConfig
}
App.vue
主要是用了configprovider组件,实现provider/inject
bootstrap.js
启动的引导方法,通过bootstarp函数间接调用了四个函数,每个函数都很重要,细说。
function bootstrap({router, store, i18n, message}) {
// 设置应用配置
setAppOptions({router, store, i18n})
// 加载 axios 拦截器
loadInterceptors(interceptors, {router, store, i18n, message})
// 加载路由
loadRoutes()
// 加载路由守卫
loadGuards(guards, {router, store, i18n, message})
}
// main.js
bootstrap({router, store, i18n, message: Vue.prototype.$message})
下一篇介绍,封装的requset请求相关,原本的登录,还有调用自己接口的登录,以及路由守卫相关