【微信小程序自学之路】如何开发自定义tabBar

微信小程序开发越来越多样化,各种丰富的设计及体验,自定义tabBar也经常使用,如:
自定义tabBar

我们来看下如何开发一个自定义的tabBar

小程序官网也有个DEMO,但是我觉得小程序文档的有很多细节没有写全,都以为大家是微信小程序开发团队,啥都知道一样。

下面是一个代码DEMO,我们将逐一讲解

app.json

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
"tabBar": {
"custom": true,
"color": "#7A7E83",
"selectedColor": "#3cc51f",
"borderStyle": "black",
"backgroundColor": "#ffffff",
"list": [
{
"pagePath": "pages/index/index",
"iconPath": "/images/icon1.png",
"selectedIconPath": "/images/icon1_selected.png",
"text": "首页"
},
{
"pagePath": "pages/good/good",
"iconPath": "/images/icon2.png",
"selectedIconPath": "/images/icon2_selected.png",
"text": "精选"
},
{
"pagePath": "pages/icon/icon",
"iconPath": "/images/icon3.png",
"selectedIconPath": "/images/icon3_selected.png",
"text": ""
},
{
"pagePath": "pages/course/course",
"iconPath": "/images/icon4.png",
"selectedIconPath": "/images/icon4_selected.png",
"text": "课程"
},
{
"pagePath": "pages/user/user",
"iconPath": "/images/icon5.png",
"selectedIconPath": "/images/icon5_selected.png",
"text": "我的"
}
]
}

这里要注意

  • app.json里面一定要添加 tabBar设置,这是为了兼容之前版本和声明哪些是tab页,但是这里的内容不会影响到tabBar的渲染,比如这里你修改color,但是渲染的自定义tabBar并不会跟着变化
  • app.json里面的tabBar设置一定要添加 “custom”: true

自定义tabBar代码结构
工程结构

这里要注意

  • 一定要在小程序根目录添加名为 custom-tab-bar 的文件夹目录
  • custom-tab-bar 里面都是 index 名的文件
  • custom-tab-bar 是一个组件 component

custom/index.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<!--components/custom-tab-bar.wxml-->
<cover-view class="tab-bar">
<cover-view class="tab-bar-border"></cover-view>
<cover-view
wx:for="{{list}}"
wx:key="index"
class="tab-bar-item {{index==2 ? 'icon' : ''}}"
data-path="{{item.pagePath}}"
data-index="{{index}}"
bindtap="switchTab"
>
<cover-image src="{{selected === index ? item.selectedIconPath : item.iconPath}}"></cover-image>
<cover-view style="color: {{selected === index ? selectedColor : color}}">{{item.text}}</cover-view>
</cover-view>
</cover-view>

这里要注意

  • 自定义tabBar的结构渲染完全由 custom-tab-bar 负责,因此这里就是tabBar的html结构了

custom/index.css

这里就不截图了

  • 这个css主要负责自定义tabBar的样式了,所有样式都要自己写
  • 根据官网建议,自定义tabBar应该fixed定位在窗口底部

custom/index.json

1
2
3
4
{
"component": true,
"usingComponents": {}
}

  • custom-tab-bar 是个component

custom/index.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
// components/custom-tab-bar.js
Component({
/**
* 组件的初始数据
*/
data: {
selected: 0,
color: "#353535",
selectedColor: "#3cc51f",
"list": [
{
"pagePath": "pages/index/index",
"iconPath": "/images/icon1.png",
"selectedIconPath": "/images/icon1_selected.png",
"text": "首页"
},
{
"pagePath": "pages/good/good",
"iconPath": "/images/icon2.png",
"selectedIconPath": "/images/icon2_selected.png",
"text": "精选"
},
{
"pagePath": "pages/icon/icon",
"iconPath": "/images/icon3.png",
"selectedIconPath": "/images/icon3_selected.png",
"text": ""
},
{
"pagePath": "pages/course/course",
"iconPath": "/images/icon4.png",
"selectedIconPath": "/images/icon4_selected.png",
"text": "课程"
},
{
"pagePath": "pages/user/user",
"iconPath": "/images/icon5.png",
"selectedIconPath": "/images/icon5_selected.png",
"text": "我的"
}
]
},

attached() {
},
methods: {
switchTab(e) {
const data = e.currentTarget.dataset
const url = data.path
console.log(data)
wx.switchTab({url})
// this.setData({
// selected: data.index
// })
}
}
})

这里要注意

  • tabBar列表数据最终是有这个组件内的 list 负责的
  • tabBar内某一项如果只有图标,那也要在 list 占位,比如上面第三项
  • 自定义tabBar的切换事件,也要自己写,switchTab事件,这个事件负责切换url
  • 很重要的一点,如果在switchTab内更新Data,比如selected项,可能会产生功能失效或者切换态失效问题,原因是切换tab页的时候,custom-tab-bar都被重新渲染了,selected都重置为初始值了。解决这个问题看下面一条

如何完美解决切换选中态的问题
上面自定义tabBar有 5 项,每一项tab页都要设置,我们以最后一项 /pages/user/user 为例

下面我们看下 /pages/user/user.js 代码

1
2
3
4
5
6
7
8
9
10
11
...
onShow() {
// 配合自定义tabBar切换
if (typeof this.getTabBar === 'function' &&
this.getTabBar()) {
this.getTabBar().setData({
selected: 4
})
}
},
...

这段代码意思是在切换到tab页之后,主动去更细tabBar的selected被选择项目,由于/pages/user/user.js属于数组下标4

个人觉得这个自定义tabBar算是小程序设计的一个不完美的地方,在业务代码(比如/pages/user/user)还去设置tabBar相关内容,耦合太大了

坚持原创技术分享,谢谢鼓励我继续创作!