自定义路由

Tips:在基础库 v3.220.0 及其以下版本存在 bug ,请勿将主包内页面路由到分包内。如业务所需可以提升基础库版本至 v3.220.0 以上。

什么是自定义路由

自定义路由是一种通过配置化的方式,由开发者指定访问路径与页面映射关系的能力。

为什么要使用自定义路由

默认情况下,页面访问路径 path 与小程序包内页面源码的目录结构一致。
例如,某小程序首页源码目录为:

  1. ├── pages
  2. └── home
  3. ├── index.js
  4. ├── index.json
  5. ├── index.css
  6. └── index.swan
  7. └── project.swan.json

那么,该页的访问路径即为 pages/home/index

这种源码目录结构与路径的紧耦合关系限制了开发者代码结构的灵活组织。

例如,一旦源码结构重构,页面路径需重新变更,导致已被搜索收录的路径失效。

通常随着业务复杂度提高,开发者常常会遇到一些需要重构源码结构的场景,比如:

  1. 产品方案变更,页面组织方式随之变化
  2. 页面功能逐渐复杂,需要拆分多个页面呈现
  3. 为了性能优化考虑,需要将部分页面移到子包中
    等。

对于以上这些场景,如果此时原来的页面路径已经有投放入口,路径变更会导致用户原访问路径失效。比如:

  1. 已被搜索收录的页面路径失效
  2. 用户分享的页面路径失效
  3. 投放在海报上的二维码路径失效
    等。

通过使用自定义路由,可以解耦源码结构与路径之间的关系,方便开发者灵活应对项目变更。

如何使用自定义路由

使用自定义路由的方式,是在 app.json 中增加路由规则字段 routes 的配置。
详见 routes 字段配置规则

当 app.json 中存在 routes 字段,框架则认为该小程序启用了自定义路由,将根据自定义路由映射规则计算。

路由映射规则

当小程序框架接收到一个页面导航指令,如 navigateTo({url: ‘/foo’}) 时:

  1. 首先从 routes 中查找 path 为 ‘foo’ 的规则,若存在,假设对应的 page 值为 ‘pages/bar/baz’,即开发者显式声明了路由映射规则:
  1. // app.json
  2. routes: [
  3. {
  4. "path": "foo",
  5. "page": "pages/bar/baz"
  6. }
  7. ]
  1. 1)框架将加载 pages/bar 目录下的 baz.jsbaz.swan 等页面源码作为要打开的目标页源码渲染。
  2. 2)如未找到上述源码文件,则当作页面路径不存在处理。
  1. 若 routes 中未找到 path 值为 ‘foo’ 的规则,则认为使用默认规则(隐式规则):
  1. // app.json
  2. routes: [
  3. {
  4. "path": "foo",
  5. "page": "foo"
  6. }
  7. ]
  1. 1)框架将加载项目根目录下的 foo.jsfoo.swan 等页面源码作为要打开的目标页源码渲染。
  2. 2)如未找到上述源码文件,当作页面路径不存在处理。

与路由有关的接口说明

本节介绍前先要明确两个概念:

path:路由路径,即访问一个小程序时 scheme 中的页面路径

page:页面源码文件路径,即某个小程序页面源码(包括页面的 js、swan、json、css)基于项目根目录的文件路径

采用自定义路由之前,路由路径 path 与页面源码文件路径 page 两个概念值一定相等。但采用自定义路由之后,被拆分为两个独立字段,其值可能不同。因此,此小节将介绍使用自定义路由之后,与导航相关的一些能力接口的含义划分。

汇总表格如下

接口含义
打开小程序的 schemepath
导航 API 中的 url 参数path
导航组件的 url 属性path
页面分享路径指定path
跳转其他小程序 API,swan.navigateToSmartProgram 的 url 参数path
页面列表,app.json 中的 pages 字段page
分包页面列表,app.json 中的 subPackages 字段page
底部导航栏对应页面,app.json 中的 tabBar 字段page

以下将基于如下示例路由规则,详细介绍各个接口的使用方式:

  • JSON
  1. // app.json
  2. {
  3. "routes": [
  4. {
  5. "path": "home",
  6. "page": "pages/home/index"
  7. },
  8. {
  9. "path": "list",
  10. "page": "subpack/shop/list"
  11. }
  12. ]
  13. }

1. 含义为路由路径(path)的能力接口

使用自定义路由后,所有导航相关的接口都会采用新的路由规则,其中包括:

(1)导航 API

其 url 参数对应自定义路由规则的 path 字段。

需注意,path 前需要加“/”表示为基于项目根路径。否则会基于当前页面计算相对路径,如:当前路径 page/foo/bar,相对路径 “home”计算结果为 page/foo/home

  • JS
  1. // 跳转首页
  2. navigateTo({url: '/home'});
  3. // 切换到 tab 页 list
  4. switchTab({url: '/list'});

(2)导航组件

其 url 属性对应自定义路由规则的 path 字段。

  • SWAN
  1. // 跳转首页
  2. <navigator open-type="navigate" url="/home">首页</navigator>
  3. // 切换到 tab 页 list
  4. <navigator open-type="switchTab" url="/list">列表</navigator>

(3)页面分享路径指定

openShare API 中的 path 参数对应自定义路由规则的 path 字段。

  • JS
  1. swan.openShare({
  2. title: '智能小程序示例',
  3. content: '世界很复杂,百度更懂你',
  4. path: '/home',
  5. imageUrl: 'https://ms-static.cdn.bcebos.com/miniappdocs/img/logo_new.png',
  6. success: res => {
  7. swan.showToast({
  8. title: '分享成功'
  9. })
  10. }
  11. })

onShareAppMessage API 中的 path 参数对应自定义路由规则的 path 字段。

  • JS
  1. onShareAppMessage(){
  2. return {
  3. title: '智能小程序示例',
  4. content: '世界很复杂,百度更懂你',
  5. path: '/home'
  6. };
  7. }

(4)打开小程序的 scheme

scheme 的 page 部分对应自定义路由规则的 path 字段,相应的基于 scheme 封装的打开小程序 sdk 中的 path 也对应自定义路由规则的 path 字段。

  1. // scheme
  2. baiduboxapp://swan/4fecoAqgCIUtzIyA4FAPgoyrc4oUc25c/home
  • JS
  1. // 引用调起 sdk 打开
  2. window.swanInvoke({
  3. appKey: '4fecoAqgCIUtzIyA4FAPgoyrc4oUc25c',
  4. path: 'home',
  5. query: {
  6. id: 1,
  7. type: 'a'
  8. }
  9. });

(5)跳转其他小程序页面 API navigateToSmartProgram

其中 path 参数对应自定义路由规则的 path 字段。

  • JS
  1. swan.navigateToSmartProgram({
  2. appKey: '4fecoAqgCIUtzIyA4FAPgoyrc4oUc25c',
  3. path: 'home',
  4. success: res => {
  5. console.log('navigateToSmartProgram success', res);
  6. })
  7. });

2. 含义为页面源码文件路径的能力接口

使用自定义路由后,有些能力接口仍然表示为页面源码文件路径,其中包括:

(1)小程序页面列表 app.json 中的 pages 字段

其每项仍表示页面的源码目录基于项目根目录的路径。

  • JSON
  1. // app.json
  2. {
  3. "pages": [
  4. "pages/home/index",
  5. ...
  6. ]
  7. }

(2)小程序分包配置 app.json 中的 subPackages 字段

其每项中的 pages 字段仍表示分包页面的源码目录基于分包目录的路径。

  • JSON
  1. // app.json
  2. {
  3. "subPackages": {
  4. "root": "subpack",
  5. "name": "subpack",
  6. "pages": [
  7. "shop/list",
  8. ...
  9. ],
  10. ...
  11. }
  12. }

(3)底部导航 tabBar 配置 app.json 中的 tabBar 字段

其中 list 字段下的每一项中,pagePath 字段仍表示此 tab 对应的页面的源码目录基于项目根目录的路径。

  • JSON
  1. // app.json
  2. {
  3. "tabBar": {
  4. "list": [
  5. {
  6. "pagePath": "subpack/shop/list",
  7. "text": "列表"
  8. },
  9. ...
  10. ]
  11. }
  12. }