自定义路由

# 什么是自定义路由

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

├── pages
│   └── home
│       ├── index.js
│       ├── index.json
│       ├── index.css
│       └── index.swan
└── project.swan.json

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

这种源码目录结构与路径的紧耦合关系限制了开发者代码结构的灵活组织。例如,一旦源码结构重构,页面路径需重新变更,导致已被搜索收录的路径失效。

通过使用自定义路由,可以解耦源码结构与路径之间的关系,方便开发者的目录灵活组织与代码重构。
使用自定义路由的方式,是在 app.json 中增加路由规则字段 routes 的配置。
详见 routes 字段配置规则

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

# 路由映射规则

当小程序框架接收到一个页面导航指令,如 navigateTo('foo') 时:

  1. 首先从 routes 中查找 path 为 'foo' 的规则,若存在,假设对应的 page 值为 'pages/bar/baz',即开发者显式声明了路由映射规则:

    // app.json
    routes: [
        {
            "path": "foo",
            "page": "pages/bar/baz"
        }
    ]
    
    • 框架将加载 pages/bar 目录下的 baz.js、baz.swan 等页面源码作为要打开的目标页源码渲染。
    • 如未找到上述源码文件,则当作页面路径不存在处理。
  2. 若 routes 中未找到 path 值为 'foo' 的规则,则认为使用默认规则(隐式规则):

    // app.json
    routes: [
        {
            "path": "foo",
            "page": "foo"
        }
    ]
    
    • 框架将加载项目根目录下的 foo.js、foo.swan 等页面源码作为要打开的目标页源码渲染。
    • 如未找到上述源码文件,当作页面路径不存在处理。

# 补充说明

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

后续介绍示例将基于如下示例路由规则讲解:

// app.json
{
    "routes": [
        {
            "path": "home",
            "page": "pages/home/index"
        },
        {
            "path": "list",
            "page": "subpack/shop/list"
        }
    ]
}

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

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

  1. 导航 API

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

    // 跳转首页
    navigateTo('home');
    // 切换到 tab 页 list
    switchTab('list');
    
  2. 导航组件

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

    // 跳转首页
    <navigator open-type="navigate" url="home">首页</navigator>
    // 切换到 tab 页 list
    <navigator open-type="switchTab" url="list">列表</navigator>
    
  3. 页面分享路径指定

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

    swan.openShare({
        title: '智能小程序示例',
        content: '世界很复杂,百度更懂你',
        path: '/pages/home/index',
        imageUrl: 'https://smartprogram.baidu.com/docs/img/logo_new.png',
        success: res => {
            swan.showToast({
                title: '分享成功'
            })
        }
    })
    

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

    onShareAppMessage(){
        return {
            title: '智能小程序示例',
            content: '世界很复杂,百度更懂你',
            path: '/pages/home/index'
        };
    }
    
  4. 打开小程序的 scheme

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

    // scheme
    baiduboxapp://swan/4fecoAqgCIUtzIyA4FAPgoyrc4oUc25c/home
    
    // 引用调起 sdk 打开
    window.swanInvoke({
        appKey: '4fecoAqgCIUtzIyA4FAPgoyrc4oUc25c',
        path: 'home',
        query: {
            id: 1,
            type: 'a'
        }
    });
    
  5. 跳转其他小程序页面 API navigateToSmartProgram

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

    swan.navigateToSmartProgram({
        appKey: '4fecoAqgCIUtzIyA4FAPgoyrc4oUc25c',
        path: 'home',
        success: res => {
            console.log('navigateToSmartProgram success', res);
        })
    });
    

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

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

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

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

    // app.json
    {
        "pages": [
            "pages/home/index",
            ...
        ]
    }
    
  2. 小程序分包配置 app.json 中的 subPackages 字段

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

    // app.json
    {
        "subPackages": {
            "root": "subpack",
            "name": "subpack",  
            "pages": [
                "shop/list",
                ...
            ],
            ...
        }
    }
    
  3. 底部导航 tabBar 配置 app.json 中的 tabBar 字段

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

    // app.json
    {
    "tabBar": {
        "list": [
            {
                "pagePath": "subpack/shop/list",
                "text": "列表"
            },
            ...
        ]
    }
    }