菜鸟读文档-Vant Weapp-3(用自己摸索的方法实现Tabbar标签栏点击跳转)
正文
似乎很好用的样例代码
我们首先将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
栏的原理理解存在问题
在微信小程序文档中的自定义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;
<span class="hljs-comment">// 删除了active数值设置相关代码</span> wx.switchTab({ <span class="hljs-attr">url</span>: <span class="hljs-keyword">this</span>.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
对象, 关于个中缘由, 只能下期再聊了