小程序中的页面跳转分为 switchTab, navigateTo, redirectTo 三个方法。每次写跳转的时候都要考虑是怎样的跳转,该使用哪个方法,这无疑是不必要的心智负担。
为了解决这个问题就编写了一个统一跳转函数,整合了3个跳转方法。

话不多说,直接看代码:

import { navigateTo, redirectTo, switchTab } from '@tarojs/taro';
import { stringifyUrl } from 'query-string';

// app.config.ts 文件中编写了 tabBar,以及主包、分包的所有路由地址
import appConfig from '../app.config';

export type Callback = (res: TaroGeneral.CallbackResult) => void;

// 接收参数定义
export type Param = {
  url: string; // 跳转地址
  params?: {
    // url 参数
    [name: string]: string | number;
  };
  close?: boolean; // 是否关闭当前页。默认为 false
  encode?: boolean; // url 参数是否 encodeURIComponent。默认为 false
  // 下面的就是3个跳转方法可以接收的
  complete?: Callback;
  fail?: Callback;
  success?: Callback;
  events?: Record<string, any>;
};

// 通过 appConfig.tabBar 就能获取到所有 tabBar 的路由地址
const tabBarUrlList: string[] = appConfig.tabBar?.list?.map((item) => '/' + item.pagePath) || [];

/**
 * 整合 navigateTo, redirectTo, switchTab
 * url 可以不传 /pages 和最前面的 /,会自动补全
 * 如:
 * /tabBar/tab2/index -> /pages/tabBar/tab2/index
 * tabBar/tab2/index -> /pages/tabBar/tab2/index
 * /personalCenter/pages/vip/index -> /pages/personalCenter/pages/vip/index
 * personalCenter/vip/index -> /pages/personalCenter/pages/vip/index
 * @param {Param} param 接收的参数
 * @example
 * - 跳转 tabBar。params, close 参数不支持
 * routTo({ url: 'tabBar/tab2/index' });
 * - 跳转普通页面,关闭当前页,即 redirectTo,params 会作为 url 参数携带
 * routeTo({ url: 'personalCenter/vip/index', params: { id: 'xxx' } });
 * - 跳转普通页面,不关闭当前页,即 navigateTo,params 会作为 url 参数携带
 * routTo({ url: 'personalCenter/vip/index', close: false, params: { id: 'xxxx' } });
 */
export default function routeTo(param: Param): Promise<TaroGeneral.CallbackResult> | void {
  let { url, params, close = false, encode = false, complete, fail, success, events } = param;

  if (!url) {
    console.error('url 为空,跳转失败');
    return;
  }

  url = url[0] === '/' ? url : '/' + url;

  // url 可以不以 /pages 开头,帮忙补全 /pages
  if (!url.startsWith('/pages')) {
    url = '/pages' + url;
  }

  if (tabBarUrlList.includes(url)) {
    // switchTab
    if (process.env.NODE_ENV === 'development') {
      if (params) {
        console.error('跳转 tabBar,params 参数无效');
      }
      if (!close) {
        console.error('跳转 tabBar,close 参数无效');
      }
    }
    return switchTab({
      url,
      complete,
      fail,
      success
    });
  } else if (close) {
    // redirectTo
    url = stringifyUrl({ url, query: params }, { encode });
    console.log('url============', url);
    return redirectTo({
      url,
      complete,
      fail,
      success
    });
  } else {
    // navigateTo
    url = stringifyUrl({ url, query: params }, { encode });
    console.log('url============', url);
    return navigateTo({
      url,
      complete,
      fail,
      success,
      events
    });
  }
}

主要思想就是可以通过 app.config.ts 拿到路由配置,从而判断跳转的页面类型,选择相应的跳转方法。

封装次函数的优点有:

  1. 不用关心跳转页面类型,减少心智负担。
  2. 由于项目架构设计主包分包都在 pages 目录下,所以可以在跳转的 url 中不传 pages,减少字符输入。
  3. url 中最前面的 / 可写可不写,会自动补全,比如从开发者工具中复制的页面路径就没有前面的 /,也能直接使用。
  4. 使用参数 close 控制跳转类型,更容易理解。使用参数 params 添加 url 参数,而不用字符串拼接,更合理。

后面项目中添加了启动页,就更体现出封装这个函数的意义了。用户可以从任意页面分享给好友,但是分享后的页面都是启动页加真实分享页面地址参数,没有这个函数就还是得判断分享的页面是不是 tabBar 从而选择对应的跳转方法,因为已经封装了这个函数,就直接使用进行跳转即可。