Vue router 实现页面组件自动加载
使用Vue全家桶开发项目已经是目前前端标配的做法。在使用vue-router实现单页应用组件路由时,我们需要将页面组件 import
进去,再注册路由,这样才可以实现路由的访问,下面是一个典型的vue-router使用方法:
// Use VueRouter
import Vue from 'vue'
import Router from 'vue-router'
Vue.use(Router)
// Import pages component
import Index from '@/pages/Index'
let routes = [{
path: '/',
component: Index
}];
const router = new Router({
routes
});
export default router;
然而,当我们的项目具有很多页面时,我们每次都要在路由数组中引入新组件,这种方法显得十分麻烦,而且在做后台管理系统时,对页面权限控制也不是很灵活。
我们希望可以在访问某个页面时,如访问 host/#/oa/event/
时,可以先判断用户角色是否具有访问权限,没有则显示 403
页面,有权限则尝试自动加载 src/pages/oa/event/index.vue
文件,加载成功后显示该页面,加在失败则显示 404
页面。
这一切操作的核心,都通过 vue-router 提供的全局前置守卫方法 router.beforeEach
来实现。
// Use VueRouter
import Vue from 'vue'
import Router from 'vue-router'
Vue.use(Router)
// Import pages component
import Index from '@/pages/Index'
let routes = [
{
path: '/',
component: Index
},
{
path: '*', // 当匹配不到任何路由时,显示404页面
component: component: () => import('@/pages/404.vue')
}
];
// 创建 router 实例
const router = new Router({
routes
});
// 实现自动加载的核心,通过 全局前置守卫方法 router.beforeEach
router.beforeEach((to, from, next) => {
// 如果matched 到的第一个路由地址为 '*', 说明该路径未注册
if (to.matched[0].path == '*') {
// 生成目标页面组件的文件路径,这里自动给路径前加上斜杆 '/'
const loadPagePath = (to.path.substr(0, 1) == '/') ? `${to.path}` : `${to.path}`;
// 尝试引入目标页面组件
// 这里需要注意的是:webpack在处理import时并不支持传入变量,但可以使用 `` 字符串模版来实现
// 还有一点要注意的是,在import的时候,不能全部使用变量,前面要有一部分路径信息才行,
// 像下面保留 @/pages 路径,在编译时,会编译 pages 下全部模块,否则提示模块不存在。
import(`@/pages${loadPagePath}`)
.then((page) => {
// console.dir(page); // 若加载成功,page是一个 Vue 组件 Object
// 生成新的路由数组信息
let newRoute = [
{
path: to.path,
component: Layout,
children: [
{
path: to.path,
component: () => import(`@/pages${loadPagePath}`)
}
]
}
]
// 追加新路由
router.addRoutes(newRoute)
// 重新转跳到目标页面,注意,这里要用 fullPath,如果用path会导致链接中的query参数丢失
router.push(to.fullPath)
})
.catch((err) => {
console.log(err)
next(); // call next() to redirect to 404 page.
})
} else {
// 这里可以用来处理其他路由拦截操作
next(); // 要调用 next() 方法才能进入下一步,否则路由会一直处于被拦截状态
}
})
export default router;
这样,我们把页面组件放在 @/pages
目录下,便可以实现像文件系统路径一样来访问对应的页面,而不需要每次新增页面的时候都修改路由文件。