# 小程序路由工具 Router

## Feature

- 进行小程序路由 `API` 二次封装，继承原有的路由属性，方便使用
- 增加路由跳转时，并自动判断该路由是否 `tabBar` 页面
- 解决页面层级超过 `10` 级无法跳转（页面层级小于 10，直接跳转；页面层级大于等于 10，若页面存在于页面栈中，回退到对应的页面栈；不存在，关闭当前页面，跳转到新页面）
- 内置 `navigateBack` 函数支持设置上一页面的数据

## Usage

```js
import routes from './config/router';

export const route = createRouter({
  routes,
});

// 内置函数方法，如下：
route.getCurrentRoute();
route.go(to);
route.push(to); // => wx.navigateTo
route.tab(to); // => wx.switchTab
route.replace(to); // => wx.redirectTo
route.relaunch(to); // => wx.reLaunch
route.back(to); // => wx.navigateBack
```

```ts
// 使用路由标识 name
await route.go({ name: 'Search' });

// 使用路由路径 url
await route.go({ ur: '/pages/search/index' });

// 添加参数
await route.go({ ur: '/pages/search/index', query: { id: '123' } });

// 手动使用不同路由类型
await route.go({ ur: '/pages/search/index', type: 'redirectTo' });

// wx.navigateTo
route.push({ name: 'Search' });

// wx.switchTab
route.tab({ name: 'Search' });

// wx.redirectTo
route.replace({ name: 'Search' });

// wx.reLaunch
route.relaunch({ name: 'Search' });

// wx.navigateBack
route.back({ delta: 1 }); // or route.back(1);
```

## API

### route.routes

小程序路由配置

#### Params

| 参数   | 说明                                               | 类型      | 必填 | 默认值  |
| ------ | -------------------------------------------------- | --------- | ---- | ------- |
| url    | 路由路径 URL，必须写全路径 `eg: /pages/home/index` | `string`  | 是   | -       |
| name   | 路由唯一标识, 可以用于判断是否非 `tabBar` 的页面   | `string`  | 是   | -       |
| title  | 路由别名名称                                       | `string`  | 否   | -       |
| tabBar | 是否 tabBar 路由页面                               | `boolean` | 否   | `false` |
| root   | 分包路由名称                                       | `string`  | 否   | -       |
| pages  | 分包路由配置                                       | `string`  | 否   | -       |
| meta   | 分包路由配置                                       | `object`  | 否   | -       |

### Example

```ts
route.routes = [
  {
    name: 'Home',
    title: '首页',
    url: '/pages/home/index',
    tabBar: true,
  },
  {
    name: 'PersonalCenter',
    title: '我的',
    url: '/pages/personal-center/index',
    tabBar: true,
  },
  {
    root: 'packages-activity',
    pages: [
      {
        name: 'GoodsActivity',
        title: '商品活动',
        url: '/packages-activity/activity/index',
        tabBar: true,
      },
    ],
  },
];
```

### router.getCurrentRoute

获取当前路由页面的配置项

```ts
function getCurrentRoute();
```

```ts
const currentRoute = router.getCurrentRoute();
/**
 * console.log(currentRoute)
 * {
 *  name: 'Home',
 *  title: '首页',
 *  url: '/pages/home/index',
 *  tabBar: true,
 *  route: 'pages/home/index',
 *  fullPath: 'pages/home/index?id=123abc',
 *  query: { id: '123abc' }
 * }
 * /
```

### route.go

小程序路由跳转

```ts
 route.go(to: RouteNavigateOption | string): Promise<RouteNavigatCallbackResul>
```

#### Params

所有的 Option 均是可选的。

| 参数     | 说明                                                                         | 类型       | 默认值       |
| -------- | ---------------------------------------------------------------------------- | ---------- | ------------ |
| url      | 路由路径 URL，必须写全路径 `eg: /pages/home/index`                           | `string`   | -            |
| name     | 路由唯一标识                                                                 | `string`   | -            |
| type     | 路由类型：`navigateTo、switchTab、redirectTo、reLaunch`                      | `string`   | `navigateTo` |
| query    | 路由参数，`eg: query: { a: 123 }`                                            | `object`   | -            |
| events   | 页面间通信接口，用于监听被打开页面发送到当前页面的数据 `(仅支持 navigateTo)` | `object`   | -            |
| success  | 接口调用成功的回调函数                                                       | `function` | -            |
| fail     | 接口调用失败的回调函数                                                       | `function` | -            |
| complete | 接口调用结束的回调函数（调用成功、失败都会执行）                             | `function` | -            |

#### Usage

```js
// 字符串路径
route.go('/pages/search/index');

// 带有路径的对象
router.go({
  url: '/pages/search/index',
});

// 带查询参数，eg: /register?plan=private
router.go({
  name: 'register',
  query: { plan: 'private' },
});

// 带跳转类型
router.go({
  name: 'search',
  type: 'switchTab',
  success: (res) => {
    console.log(res);
  },
});

// 进行页面通信, 只适用于类型是navigateTo
router.go({
  name: 'search',
  events: {
    // 为指定事件添加一个监听器，获取被打开页面传送到当前页面的数据
    acceptDataFromOpenedPage(data) {
      console.log(data)
    },
    someEvent(data) {
      console.log(data)
    }
    ...
  },
  success: (res) => {
    // 通过eventChannel向被打开页面传送数据
    res.eventChannel.emit('acceptDataFromOpenerPage', { data: 'test' })
  },
});

// 异步 Promise
await router.go({ url: '/pages/search/index' })
```

### router.push

继承小程序 `wx.navigateTo` 用法， 保留当前页面，跳转到应用内的某个页面。但是不能跳到 `tabbar` 页面

```ts
async function push(to: RouteNavigateOption | string);
```

### router.tab

继承小程序 `wx.switchTab` 用法，跳转到 `tabBar` 页面，并关闭其他所有非 `tabBar` 页面

```ts
async function tab(to: RouteNavigateOption | string);
```

### router.replace

继承小程序 `wx.redirectTo` 用法，关闭当前页面，跳转到应用内的某个页面。但是不允许跳转到 `tabbar` 页面

```ts
async function replace(to: RouteNavigateOption | string);
```

### router.relaunch

继承小程序 `wx.reLaunch` 用法，关闭所有页面，打开到应用内的某个页面

```ts
async function relaunch(to: RouteNavigateOption | string);
```

### router.back

继承小程序 `wx.navigateBack` 用法，关闭所有页面，打开到应用内的某个页面, 同时支持设置上一页面的数据

```ts
async function back(to: WechatMiniprogram.RouteNavigateBackOption);
```

```ts
router.back({
  delta: 1,
  data: { name: 'aidendu', work: 'javascript' }, // 设置上一页面的数据
});
```
