// 这里有一个坑,一定要注意这一步和上一步得分开写
// 如果把前两步判断合并为 if (!token) next({ name:login })
// 则会形成登录页面无限刷新的错误,具体成因后面解释
next()
} else {
// 如果登录了
if (!store.state.app.hasGetRoute) {
// 如果没有获取路由信息,先获取路由信息而后跳转
store.dispatch('getRouteList').then(() => {
router.addRoutes(store.state.app.routeList)
// 这里也是一个坑,不能使用简单的 next()
// 如果直接使用 next() 刷新后会一直白屏
next({ ...to, replace: true })
})
} else {
// 如果已经获取路由信息,直接跳转
next()
}
}
})
export default router
// store/index.js
import router from '@/router'
import Main from '@/components/main'
import { getToken } from '@/lib/util'
import { getRoute } from '@/api/app'const loadView = (viewPath) => {
// 用字符串模板实现动态 import 从而实现路由懒加载
return () => import(`@/view/${viewPath}`)
}
const filterAsyncRouter = (routeList) => {
return routeList.map((route) => {
if (route.component) {
if (route.component === 'Main') {
// 如果 component = Main 说明是布局组件
// 将真正的布局组件赋值给它
route.component = Main
} else {
// 如果不是布局组件就只能是页面的引用了
// 利用懒加载函数将实际页面赋值给它
route.component = loadView(route.component)
}
// 判断是否存在子路由,并递归调用自己
if (route.children && route.children.length) {
route.children = filterAsyncRouter(route.children)
}
}
})
}
export default {
state: {
routeList: [],
token: getToken(),
hasGetRoute: false
},
mutations: {
setRouteList(state, data) {
// 先将 JSON 格式的路由列表解析为 JavaScript List
// 再用路由解析函数解析 List 为真正的路由列表
state.routeList = filterAsyncRouter(JSON.parse(data))
// 修改路由获取状态
state.hasGetRoute = true
}
},
atcions: {
getRouteList({ state, commit }) {
return new Promise((resolve) => {
const token = state.token
getRoute({ token }).then((res) => {
let data = res.data.data
// 注意这里取出的是 JSON 格式的路由列表
commit('setRouteList', data)
resolve()
})
})
}
}
}
常见问题
页面卡在登录页面而且不断刷新
这个问题的解决方案在「实现代码」中已经提到了,只需要在判断登录状态的时候注意不要将两种未登录状态混为一谈即可。但这样治标不治本,因为同样的问题可以由不同形式的代码导致,那导致问题的原因是什么那?然我们慢慢分析:










