菜鸟读文档-Vant Weapp-3(用自己摸索的方法实现Tabbar标签栏点击跳转)

2,107 阅读4分钟

正文

似乎很好用的样例代码

我们首先将 Vant WeappTabbar 标签栏文档基础用法样例直接复制到 custom-tab-bar 文件夹中

  • index.wxml

    <!-- 为了方便演示, 我将样例中的 tabbar 数量减少到两个 -->
    <van-tabbar>
      <van-tabbar-item icon="home-o">标签1</van-tabbar-item>
      <van-tabbar-item icon="search">标签2</van-tabbar-item>
    </van-tabbar>
    
  • index.js

    Page({
      data: {
        active: 0,
      },
      onChange(event) {
        // event.detail 的值为当前选中项的索引
        this.setData({
          active: event.detail
        });
      },
    });
    

在输入完基础用法样例中的代码后发现: 点击 tabbar 子项后, 该子项将会进入活跃状态. 我们需要的 tabbar 点击跳转功能就已经实现一半了(什么嘛,文档样例还是挺好用的嘛)

接下来需要做的就是在 tabbar 子项进入活跃状态的同时进入到对应的页面

问题多多的页面跳转

既然我们的 tabbar 栏只剩下页面跳转功能需要实现了, 我们就直接去微信小程序文档中找到相应的路由API: wx.switchTab, 按照文档中的样例输入到自己项目中的 index.js 文件中就完事了(然而欲速则不达啊...)

为了让代码更可读, 我们将代码稍微修改一下

  • index.js

    Page({
      data: {
        // 将 tabbar 需要的所有数据全部封装到 tabbars 对象中
        tabbars: {
          // tabbar 所有的子项
          list: [{
            pagePath: "/pages/page1/page1",
            text: "第一页",
            icon: "home-o"
          }, {
            pagePath: "/pages/page2/page2",
            text: "第二页",
            icon: "search"
          }],
          // 当前活跃的 tabbar 子项
          active: 0,
        },
      },
      onChange: function(event) {
        // event.detail 的值为当前选中项的索引
        console.log(event.detail);
        const index = event.detail;
        // 活跃 tabbar 子项设置
        this.setData({
          "tabbars.active": index
        });
        // 页面路由
        wx.switchTab({
          url: this.data.tabbars.list[index].pagePath
        });
      },
    });
    
  • index.wxml

    <van-tabbar active="{{tabbars.active}}" bind:change="onChange">
      <block wx:for="{{tabbars.list}}" wx:key="text">
        <van-tabbar-item icon="{{item.icon}}">{{item.text}}</van-tabbar-item>
      </block>
    </van-tabbar>
    

然而在代码输入完成后, 测试却发现实际效果并不和预想中的一样...

从 gif 图中可以看到, 在按下 tabbar 子项进行跳转后, 上方页面实现了正常的页面跳转, 但下方 tabbar 栏中的子项却没有进入对应的活跃状态...

分析问题

从出现的问题我们可以看出: 当使用 tabbar 栏进行页面跳转时, tabbar 子项的活跃状态会保持之前的活跃状态, 而不是随页面跳转而相应变化, 即 index.js 文件中 tabbars 对象的 active 属性的值没有进行相应的改变

在微信小程序文档中的自定义 tabBar, 我找到了如下内容

每个 tab 页下的自定义 tabBar 组件实例是不同的,可通过自定义组件下的 getTabBar 接口,获取当前页面的自定义 tabBar 组件实例。

...

对于这段话的我的理解是: 每当使用 wx.switchTab() 切换到一个新的 tab 页后, 该页面下的自定义 tabbar 栏都会基于 custom-tab-bar 文件夹下的文件重新渲染, 又因为在 index.js 中, tabbars 对象的 active 属性的值默认设置为0, 因此每一次从当前 tab 页切换到新的 tab 页时, 底部 tabbar 栏都会是第一个 tabbar 子项为活跃状态, 如下图所示(为了演示, 我加入了第三个 tabbar 子项):

上述 gif 图实际上的路由逻辑是:

  1. 从页面1路由到页面2
  2. 从页面2路由到页面3

可以看到, 每一次路由到新的页面, 底部 tabbar 栏都会是第一个 tabbar 子项为活跃状态

自己摸索的方法

基于以下已知的情况:

  1. 每一次路由到新的页面都会重新渲染底部的 tabbar
  2. index.js 文件中 tabbars 对象的 active 属性设置默认值会导致底部 tabbar 栏子项活跃状态和目标页面不匹配

那我认为可以这样处理:

  1. 取消 tabbars 对象的 active 属性的默认值

    active: null
    
  2. 利用 this.getTabBar().setData() 接口, 在目标页面为 tabbar 栏设置对应的活跃状态

    • index.js

        onChange: function(event) {
          // event.detail 的值为当前选中项的索引
          const nextIndex = event.detail;
          
          // 删除了 active 数值设置相关代码
          
          wx.switchTab({
            url: this.data.tabbars.list[nextIndex].pagePath
          });
        }
      
    • page1.js (其它需要通过 tabbar 路由的页面也需要编写相应代码)

        // 在页面的 onLoad 周期设置对应的活跃 tabbar 项
        onLoad: function (options) {
          this.getTabBar().setData({
            // CURRENT_ACTIVE_TABBAR: 自定义常量, 当前页面对应的活跃 tabbar 项
            "tabbars.active": CURRENT_ACTIVE_TABBAR
          });
        },
      

输入上述代码之后, 效果如下图所示:

可以看到路由页面和下方 tabbar 栏中子项的激活状态是对应的了

预告

从组件的角度处理自定义 tabbar

虽然用自己摸索的方法似乎将问题解决了, 但是, 我在微信小程序文档中的自定义 tabBar, 又找到了如下内容:

注意:如需实现 tab 选中态,要在当前页面下,通过 getTabBar 接口获取组件实例,并调用 setData 更新选中态。可参考底部的代码示例

...

微信小程序文档中提供的实现 tab 选中态代码的核心虽然也是 this.getTabBar().setData() 接口, 但却不像 Vant Weapp 文档中那样, 将自定义 tabbar 栏处理为 Page 对象, 而是处理为 Component 对象, 关于个中缘由, 只能下期再聊了:)

菜鸟读文档-Vant Weapp-4(小程序文档样例对Tabbar组件的处理)