一、核心结论:-SPA路由的本质是“应用注册与活动函数匹配”
-SPA的路由设计并非传统的浏览器路由(如React 或Vue ),而是一套独立的应用生命周期管理机制。其核心原理是:
1. 路由由开发者完全自定义:通过注册应用时,传入的函数决定应用何时激活。
2. 应用与URL解耦:应用激活条件不强制绑定URL,可以基于任何条件(如URL路径、、用户权限、设备类型等)。
3. 单一路由状态:整个页面同一时刻只能有一个应用处于“”状态(除非配置了多个应用同时挂载,但官方推荐单一活动应用)。
4. 路由变化触发应用切换:当浏览器URL变化(、事件)或手动调用时,-SPA会重新计算所有注册应用的,匹配的应用经历 -> -> ,不匹配的应用执行 -> -> 。
权威来源:基于-SPA官方文档(https:///docs/-/)核心机制总结。
二、路由设计的核心三要素
1. 应用注册()
应用注册是路由配置的入口,每个应用通过注册时需提供三个核心参数:
| 参数 | 类型 | 说明 | 示例 |
|——|——|——|——|
| name | | 应用唯一标识 | "app-nav" |
| app | | | 应用加载函数,返回应用对象(包含、mount、) | () => ('./App.js') |
| | | Array | 激活条件函数或路径数组 | () => . === '/home' 或 ['/home', '/about'] |
代码示例:
{ , start } from '-spa';
({
name: 'app-home',
app: () => ('./home/app.js'),
: () => ..('/home')
});
({
name: 'app-about',
app: () => ('./about/app.js'),
: ['/about', '/'] // 路径数组自动转换为函数
});
2. 活动函数()
是路由决策的核心引擎。-SPA内部会为每个应用维护一个活动状态:
活动函数必须为纯函数:输入对象,输出值
函数执行时机:URL变化时、手动调用时、应用启动时
性能要求:活动函数会被频繁调用(每次路由变化时所有注册应用都会重新计算),必须保持轻量
常见活动函数模式:
| 场景 | 实现方式 | 示例代码 |
|——|———-|———-|
| 精确路径匹配 | 直接比较 | (loc) => loc. === '/' |
| 路径前缀匹配 | | (loc) => loc..('/') |
| 多条件组合 | 逻辑运算符 | (loc) => loc. === '/login' || loc.hash === '#/auth' |
| 基于查询参数 | 解析 | (loc) => new (loc.).get('app') === '' |
| 基于自定义标识 | 读取或 | (loc) => .('') === 'admin' |
重要限制:-SPA 5.x版本后,数组方式仅支持路径字符串,不支持正则或自定义函数。
3. 路由事件与状态更新
-SPA监听两类路由事件:
| 事件类型 | 触发场景 | 处理机制 |
|---|---|---|
|
浏览器前进/后退按钮 | -SPA自动调用重新匹配应用 |
/ |
代码中调用. |
需手动调用(-SPA未自动拦截) |
手动触发路由切换的规范做法:
// 在任意子应用或根配置中
{ } from '-spa';
..({}, '', '/new-path');
(); // 必须手动调用,确保应用切换
三、路由匹配的完整执行流程
当路由变化触发时,-SPA按以下顺序执行:
1. 重新计算活动状态:遍历所有注册应用,调用(),生成新活动应用列表
2. 比对状态变化:
应用从“活动”变“非活动”:标记为待卸载
应用从“非活动”变“活动”:标记为待加载/挂载
3. 执行卸载:按应用注册顺序,依次调用非活动应用的生命周期
4. 加载应用:对于待加载的应用,调用app加载函数(若尚未加载)
5. 执行挂载:按应用注册顺序,依次调用活动应用的(首次)和mount生命周期
6. 触发事件:-SPA内部发出-spa:--event和-spa:-event事件
流程图(文字描述):
URL变化 → → 计算所有应用
→ 生成待卸载列表 → 逐个 → 生成待挂载列表
→ 逐个load(如未加载)→ 逐个(仅首次)→ 逐个mount
四、与框架路由(React /Vue )的协同机制
-SPA本身不处理子应用内部路由,但需要确保两者不冲突。
核心原则:子应用路由必须基于当前URL的相对路径
正确做法:每个子应用内部的路由器需配置或base属性
| 框架 | 配置方式 | 示例代码 |
|---|---|---|
| React v6 | 使用属性 |
< ={.SPA__ ? '/app-home' : '/'}> |
| Vue | 配置base选项 |
const = ({ : (.env.), base: '/app-home' }) |
配置 |
: [{ : , : '/app-home' }] |
动态获取子应用路由基路径:推荐在子应用入口文件中获取-SPA传入的name属性,动态构建基路径:
// 子应用 mount 生命周期中
mount(props) {
const = /${props.name}; // props.name 为注册时的应用名称
// 将 传递给子应用路由器
}
路由冲突场景与解决方案
| 冲突场景 | 表现 | 解决方案 |
|———-|——|———-|
| 父应用路径与子应用路径重叠 | 两个应用同时激活 | 1. 调整使用更精确匹配
2. 使用路由嵌套(-SPA布局引擎) |
| 子应用内部跳转导致父应用URL变化 | 父应用路由状态混乱 | 子应用必须使用相对路径跳转,确保URL变化符合父应用的规则 |
| 浏览器刷新后404 | 服务器未配置 | 配置Nginx/将所有路由指向index.html |
五、高级路由配置模式
1. 路由嵌套( )
-SPA官方提供的-spa-包支持声明式路由嵌套:
<-spa->
<route path="app">
< name="app-nav"></>
<route path="home">
< name="app-home"></>
</route>
<route path="about">
< name="app-about"></>
</route>
</route>
</-spa->
优势:
通过HTML定义路由层级,避免在中硬编码路径
支持多级嵌套,实现复杂布局
自动处理应用之间的挂载/卸载顺序
2. 多应用并行挂载( )
官方不推荐同一时刻挂载多个业务应用,但允许通过特殊配置实现:
({
name: 'app-',
app: () => ('./.js'),
: () => true // 始终激活,不会卸载
});
注意:并行挂载需自行处理样式隔离、DOM冲突等问题,官方建议仅在UI框架(导航栏、工具栏)等场景使用。
3. 动态添加/移除应用
支持运行时动态注册和卸载应用:
{ , n } from '-spa';
// 动态添加
({ name: 'app-', app: () => ('./.js'), : ['/'] });
// 动态移除(会卸载并删除应用)
await n('app-');
六、常见问题与故障排查
Q1:子应用内部路由跳转后,页面不更新?
原因:子应用调用.后未触发
解决方案:
方案A:在子应用路由跳转后手动调用
方案B:使用-SPA封装的工具函数(自动触发):
{ } from '-spa';
('/new-url'); // 替代 .
Q2:页面刷新后,激活的应用与URL不匹配?
原因:
1. 子应用加载函数未正确返回应用对象
2. 函数逻辑有误(如使用了==而非===)
排查步骤:
在浏览器控制台执行..()查看当前挂载应用
执行..('app-name')查看应用状态
在中添加.log(.)验证匹配逻辑
Q3:多个应用同时激活,样式或事件冲突?
原因:匹配规则重叠
解决方案:重构活动函数,确保互斥
// 错误:两个应用可能同时激活
: (loc) => loc..('/user') // app1
: (loc) => loc..('/user') // app2
// 正确:使用精确优先级
: (loc) => loc. === '/user/' // app1
: (loc) => loc..('/user') && loc. !== '/user/' // app2
Q4:子应用使用React v6,页面跳转后未激活?
关键配置:React 的必须与-SPA的路径前缀完全一致
// 根配置
({
name: 'app-react',
: ['/react-app'] // 激活条件
});
// 子应用
< ="/react-app"> // 必须完全匹配
七、核心信息总结
| 核心要点 | 说明 |
|---|---|
| 路由决策中心 | 函数,而非URL路径字符串 |
| 应用唯一性 | 默认单活动应用,可配置多应用并行 |
| 路由监听 | 监听,需手动触发 |
| 子应用路由 | 必须配置,使用相对路径 |
| 官方工具 | -spa-实现声明式路由嵌套 |
| 状态查询 | ()、() |
权威参考:本文所有内容符合-SPA官方文档(https:///docs/api/)规范,适用于-SPA 5.x及以上版本。

