正文
似乎很好用的样例代码
我们首先将 Vant Weapp
中 Tabbar 标签栏文档的基础用法样例直接复制到 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路由到页面2
- 从页面2路由到页面3
可以看到, 每一次路由到新的页面, 底部 tabbar
栏都会是第一个 tabbar
子项为活跃状态
自己摸索的方法
基于以下已知的情况:
- 每一次路由到新的页面都会重新渲染底部的
tabbar
栏 index.js
文件中tabbars
对象的active
属性设置默认值会导致底部tabbar
栏子项活跃状态和目标页面不匹配
那我认为可以这样处理:
-
取消
tabbars
对象的active
属性的默认值active: null
-
利用
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
对象, 关于个中缘由, 只能下期再聊了:)