当前位置: 首页 > 文档资料 > Lavas 教程 >

router-loader 介绍

优质
小牛编辑
130浏览
2023-12-01

仅有Lavas MPA 模板包含此功能

问题背景

在单页应用中我们使用 vue-router 进行前端路由跳转,而多页应用可以看成多个单页应用,每个单页都可以有各自独立的路由,那么如何做到在各个单页之间进行跳转呢?

例如想从A页面跳转到B页面,发现目标路由规则并不在A页面的规则集中,此时肯定不能展示404页面,需要识别出这是一个有效的路由规则,通过window.location.href而非 vue-router 进行强制跳转。

这就要求我们在构建时收集所有页面使用的路由规则,形成一个项目中有效的路由规则全集。各个页面遇到不匹配的路由时,都需要去这个全集中查看,匹配了其中的某条规则才进行强制跳转,否则依然展示404页面。

具体实现

依据以上实现思路,首先在通用路由生成函数中,加入通用路由处理规则*,在beforeEnter钩子中使用validateRoute校验目标路由是否匹配项目中使用到的合理规则,校验失败依旧展示404页面。

// src/router.js

export function createRouter({routes = []}) {
    const router = new Router({
        routes: [
            ...routes,
            {
                path: '*',
                component: NotFound,
                beforeEnter(to, from, next) {
                    // 有效路由,跳转
                    if (validateRoute(to.fullPath)) {
                        window.location.href = to.fullPath;
                        return;
                    }
                    next(); // 无效路由,展示404页面
                }

validateRoute方法中,由于动态路由的存在,需要对动态参数进行替换,使用正则进行匹配。

function validateRoute(path) {
    return allRoutes.includes(path)
        || allRoutes.some(route => {
            // 生成路由路径对应的正则表达式 /detail/:id => /^\/detail\/[^\/]+\/?$/
            let routeRegex = new RegExp(`^${route.replace(/\/:[^\/]*/g, '/[^\/]+')}\/?$`);
            return routeRegex.test(path);
        });
}

对于路由规则全集allRoutes,将由 router-loader 负责收集。

router-loader 实现

首先明确路由全集的注入点,在src/router.js中,我们需要将路由全集放入数组allRoutes中。

// src/router.js

const allRoutes = [];

Lavas MPA 模板中,每个页面有独立的路由文件:

lavas-template-vue-mpa
    |---src
        |---pages 页面存放目录
            |---detail 详情页模块
                |--- Detail.skeleton.vue 构建时渲染的skeleton组件
                |--- Detail.vue 路由组件
                |--- entry-skeleton.js skeleton入口
                |--- entry.js entry入口
                |--- index.html 页面模板,供htmlWebpackPlugin使用
                |--- router.js 单页面使用的路由
            |---home 主页模块
            |---search 搜索页模块
        |---...省略其他目录

router-loader 只需要遍历各个页面的路由文件,从内容中提取出使用的路由规则路径(例如path: '/home'),拼接后注入。 另外,在 svg-loader介绍一文中提到了监听文件更新的问题,这里我们也将每个路由文件加入了 webpack 监听文件列表,方便开发使用。

// src/router.js插入点
let pos = source.indexOf(INSERT_POSITION) + INSERT_POSITION.length;
// 各个页面路由路径
let entryRouters = utils.getEntries('./src/pages', 'router.js');
let routePaths = [];
for (let entryName in entryRouters) {
    if (entryRouters.hasOwnProperty(entryName)) {
        let routerPath = path.resolve(__dirname, '../../', entryRouters[entryName]);
        // 读取各个页面路由文件内容
        let content = fs.readFileSync(routerPath, 'utf8');
        // 解析内容中的路径
        routePaths = routePaths.concat(extractRoutePaths(content));
        // 加入文件监听列表
        this.addDependency(routerPath);
    }
}
// 拼接所有路由路径,注入
return insertAt(source, routePaths.join(','), pos);