wx.redirectTo() 可以说是我在编写微信小程序的过程中用到最多的一个页面转跳的路由 API。因为微信小程序不像React、Vue 一样是 SPA,所以路由 API 的使用其实很大程度上决定了编写的微信小程序性能以及速度。在这种情况下,了解每个用到的路由 API 并学会正确使用就显得尤为重要。

    微信原生主要提供了以下几个用于页面转跳的 API:

    1. wx.switchTab() // 跳转到 tabBar 页面,并关闭其他所有非 tabBar 页面
    2. wx.reLaunchTo() // 关闭所有页面,打开到应用内的某个页面
    3. wx.redirectTo() // 关闭当前页面,跳转到应用内的某个页面。但是不允许跳转到 tabbar 页面。
    4. wx.navigateTo() // 保留当前页面,跳转到应用内的某个页面。但是不能跳到 tabbar 页面。可以返回到原页面。
    5. wx.navigateBack() // 关闭当前页面,返回上一级或多级页面。可通过 getCurrentPages 获取页面栈,并决定返回几层。

    这些 API 都有各自的作用,所以理论上都可以运用到不同的转跳的地方。但有一点不同的是 wx.redirectTo() 的使用要求是小程序基础库版本不低于 2.2.2,而wx.swtichTab() 的使用条件则是小程序基础库版本不低于 2.3.1 —— 说明实际上wx.redirectTo 是一个相对而言更久远的 API,而wx.swtichTab() 则是后续版本更新的 API。所以我就想到了一个问题,这两个 API 从效率上看,究竟谁更胜一筹。

    要回答这个问题,还需要从 API 的源码看起。首先是 wx.redirectTo() 的源码,微信小程序的源码都是用了TypeScript 来编写,所以对本菜鸟来说阅读起来肯定不是很方便,但是好在作为一个中国开发者编写的 API,里面有很多的注释。

    1. /** [wx.redirectTo(Object object)](https://developers.weixin.qq.com/miniprogram/dev/api/route/wx.redirectTo.html)
    2. *
    3. * 关闭当前页面,跳转到应用内的某个页面。但是不允许跳转到 tabbar 页面。
    4. *
    5. * **示例代码**
    6. *
    7. *
    8. * ```js
    9. wx.redirectTo({
    10. url: 'test?id=1'
    11. })
    12. ``` */
    13. redirectTo < TOption extends RedirectToOption >(
    14. option: TOption
    15. ): PromisifySuccessResult<TOption, RedirectToOption>

    从源码上来看,可以清晰地发现,wx.redirectTo()继承了 RedirectToOption,为了使得它具有 Promise 的能力,还引入了PromisifySuccessResult,所以这里把这两个的源码也逐一展示。

    1. /**********************************************************************************/
    2. // RedirectToOption 的源码部分
    3. interface RedirectToOption {
    4. /** 需要跳转的应用内非 tabBar 的页面的路径 (代码包路径), 路径后可以带参数。参数与路径之间使用 `?` 分隔,参数键与参数值用 `=` 相连,不同参数用 `&` 分隔;如 'path?key=value&key2=value2' */
    5. url: string
    6. /** 接口调用结束的回调函数(调用成功、失败都会执行) */
    7. complete?: RedirectToCompleteCallback
    8. /** 接口调用失败的回调函数 */
    9. fail?: RedirectToFailCallback
    10. /** 接口调用成功的回调函数 */
    11. success?: RedirectToSuccessCallback
    12. }
    13. /** 接口调用结束的回调函数(调用成功、失败都会执行) */
    14. type RedirectToCompleteCallback = (res: GeneralCallbackResult) => void
    15. /** 接口调用失败的回调函数 */
    16. type RedirectToFailCallback = (res: GeneralCallbackResult) => void
    17. /** 接口调用成功的回调函数 */
    18. type RedirectToSuccessCallback = (res: GeneralCallbackResult) => void
    19. /********************************************************************************/
    20. // PromisifySuccessResult 的源码部分
    21. type PromisifySuccessResult<
    22. P,
    23. T extends AsyncMethodOptionLike // 确定了 Async 的方法
    24. > = P extends { success: any }
    25. ? void
    26. : P extends { fail: any }
    27. ? void
    28. : P extends { complete: any }
    29. ? void
    30. : Promise<Parameters<Exclude<T['success'], undefined>>[0]>

    可以看到这里经过RedirectToOptionPromisifySuccessResult的处理之后,wx.redirectTo()已经具备了类似 Promise的异步能力,可以编写 success fail compelete这三个回调函数,整体代码很易懂。而wx.switchTab()在使用方面实际上和wx.redirectTo()是基本一样的,都是关闭当前的(非 tabBar)页面,并转跳到(tabBar)页面。

    1. /***************************************************************************************************/
    2. /** [wx.switchTab(Object object)](https://developers.weixin.qq.com/miniprogram/dev/api/route/wx.switchTab.html)
    3. *
    4. * 跳转到 tabBar 页面,并关闭其他所有非 tabBar 页面
    5. *
    6. * **示例代码**
    7. *
    8. * ```json
    9. {
    10. "tabBar": {
    11. "list": [{
    12. "pagePath": "index",
    13. "text": "首页"
    14. },{
    15. "pagePath": "other",
    16. "text": "其他"
    17. }]
    18. }
    19. }

    *

    • js wx.switchTab({ url: '/index' }) */ switchTab( option: TOption ): PromisifySuccessResult

    interface SwitchTabOption { / 需要跳转的 tabBar 页面的路径 (代码包路径)(需在 app.json 的 tabBar 字段定义的页面),路径后不能带参数。 */ url: string / 接口调用结束的回调函数(调用成功、失败都会执行) / complete?: SwitchTabCompleteCallback /** 接口调用失败的回调函数 / fail?: SwitchTabFailCallback /* 接口调用成功的回调函数 / success?: SwitchTabSuccessCallback }

    / 接口调用结束的回调函数(调用成功、失败都会执行) */ type SwitchTabCompleteCallback = (res: GeneralCallbackResult) => void / 接口调用失败的回调函数 / type SwitchTabFailCallback = (res: GeneralCallbackResult) => void /** 接口调用成功的回调函数 / type SwitchTabSuccessCallback = (res: GeneralCallbackResult) => void

    type PromisifySuccessResult< P, T extends AsyncMethodOptionLike

    = P extends { success: any } ? void : P extends { fail: any } ? void : P extends { complete: any } ? void : Promise>[0]> ```

    可以看到,两者确实是基本相似的,所以在普通的页面转跳方面应该是差别不大的。但可以看到wx.redirectTo()是限制了不能转跳tabBar页面的,而wx.switchTab()则限制了只能转跳tabBar页面,根据这个 API 接口的描述,理论上讲应该是不关闭tabBar页面的,所以在频繁转跳tabBar页面的过程中,**wx.switchTab()**应该是明显比**wx.redirectTo()**要来得更快,编写代码的时候也会方便很多。当然,我们也可以自己封装一个tabBar,只使用wx.redirectTo()来进行页面转跳。虽然一定程度上自己封装的tabBar也许比switchBar要慢一些,但是使用wx.redirectTo()来进行页面转跳也避开了一些wx.switchTab()的限制,例如不能转入非tabBar页面。

    1. <!--pages/Botton_menu/Bottom_menu.wxml-->
    2. <view class='bottomrow'>
    3. <view class="bottomtab" bindtap="select1">
    4. <image class="bottomtabimage" src="{{saishi}}"></image>
    5. <view class="bottomtext">
    6. <text style="color:{{bcolor1}}">绿茵场</text>
    7. </view>
    8. </view>
    9. <view class="bottomtab" bindtap="select2">
    10. <image class="bottomtabimage" src="{{fabuhui}}"></image>
    11. <view class="bottomtext">
    12. <text style="color:{{bcolor2}}">发布会</text>
    13. </view>
    14. </view>
    15. <view class="bottomtab" bindtap="select3">
    16. <image class="bottomtabimage" src="{{shipin}}"></image>
    17. <view class="bottomtext">
    18. <text style="color:{{bcolor3}}">野球局</text>
    19. </view>
    20. </view>
    21. <view class="bottomtab" bindtap="select4">
    22. <image class="bottomtabimage" src="{{gengduo}}"></image>
    23. <view class="bottomtext">
    24. <text style="color:{{bcolor4}}">更衣室</text>
    25. </view>
    26. </view>
    27. </view>
    1. /* pages/Botton_menu/Bottom_menu.wxss */
    2. .bottomrow{
    3. background-color: rgb(244, 244, 255);
    4. width: 100%;
    5. height: 9%;
    6. bottom: 0rpx;
    7. position: fixed;
    8. display: flex;
    9. flex-direction: row;
    10. justify-content: center;
    11. align-items: center;
    12. }
    13. .bottomtab{
    14. width: 166rpx;
    15. display: flex;
    16. flex-direction: column;
    17. align-items: center;
    18. justify-content: center;
    19. }
    20. .bottomtabimage{
    21. margin-top: 10rpx;
    22. width: 55rpx;
    23. height: 55rpx;
    24. }
    25. .bottomtext{
    26. font-size: 18rpx;
    27. font-weight: bold;
    28. color: rgb(13,65,140);
    29. justify-content: center;
    30. align-items: center;
    31. margin-top: 10rpx;
    32. }

    JavaScript 函数方面,主要写了以下几个转跳函数

    1. /* 底部导航栏选择 */
    2. select1: function () {
    3. wx.redirectTo({
    4. url: '/pages/game/game',
    5. })
    6. },
    7. select2: function () {
    8. wx.redirectTo({
    9. url: '/pages/square/square',
    10. })
    11. },
    12. select3: function () {
    13. wx.redirectTo({
    14. url: '/pages/getGame/getGame',
    15. })
    16. },
    17. select4: function () {
    18. wx.redirectTo({
    19. url: '/pages/Person/Person',
    20. })
    21. },

    根据小程序的特点,让底部栏的图片和文字颜色由 data 里面的变量来控制,当然也可以通过转跳时带参数进行控制。

    1. data: {
    2. bcolor1: "rgb(13,65,140)", // 被选中的颜色
    3. bcolor2: "rgb(180,180,180)", // 未选中的颜色
    4. bcolor3: "rgb(180,180,180)", // 未选中的颜色
    5. bcolor4: "rgb(180,180,180)", // 未选中的颜色
    6. saishi: "/images/icons/bottom/saishi.png", // 被选中的图标
    7. fabuhui: "/images/icons/bottom/fabuhui2.png", // 未选中的图标
    8. shipin: "/images/icons/bottom/shipin2.png", // 未选中的图标
    9. gengduo: "/images/icons/bottom/gengduo2.png", // 未选中的图标
    10. }

    于是就能得到下图所示的效果,基本实现了一个底部栏的操作。

    1.jpg

    实际上此处使用自己编写的tabBar的原因,完全是因为页面里处了底部栏还有一个二级顶部栏。
    2.jpg
    为了使得顶部栏切换时不用使得底部栏消失,切换起来更方便,于是使用了自己编写的tabBar,在wx.redirectTo()的规则下,可以更加自由地进行转跳。
    想要体验该小程序可以在微信搜索 踢在浙大,或访问 踢在浙大 v1.0的仓库:https://github.com/users/MMMarcinho/projects/2