赞
踩
微信小程序提供的原生 tab-bar 功能简单,样式单一,无法满足业务需求。
项目中使用的是 wepy 1.x 框架,实现原理与原生类似。
修改全局配置
// app.wpy
export default class extends wepy.app {
config = {
tabBar: {
custom: true,
// ...
}
}
}
编写 tab-bar
组件
<!-- CustomTabBar.wpy --> <template> <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" data-path="{{item.pagePath}}" data-index="{{index}}" bindtap="switchTab"> <cover-image class="icon" 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> </template> <script> import wepy from 'wepy'; export default class CustomTabBar extends wepy.component { props = { selected: { type: String, default: '0' } } data = { color: '#7A7E83', selectedColor: '#6280f5', list: [ { selectedIconPath: '../images/tab_application_pre.png', iconPath: '../images/tab_application.png', pagePath: '/pages/Application', text: '应用' }, { selectedIconPath: '../images/tab_project_pre.png', iconPath: '../images/tab_project.png', pagePath: '/pages/Machines', text: '机械' }, { selectedIconPath: '../images/tab_message_pre.png', iconPath: '../images/tab_message.png', pagePath: '/pages/Message', text: '消息' }, { selectedIconPath: '../images/tab_mine_pre.png', iconPath: '../images/tab_mine.png', pagePath: '/pages/MyHome', text: '我的' } ] } methods = { switchTab(e) { const data = e.currentTarget.dataset; const url = data.path; wx.switchTab({ url }); } } } </script> <style lang='less' scoped> .tab-bar { position: fixed; bottom: 0; left: 0; right: 0; height: 160rpx; background: white; display: flex; padding-top: 8rpx; padding-bottom: env(safe-area-inset-bottom); .tab-bar-border { background-color: rgba(0, 0, 0, 0.33); position: absolute; left: 0; top: 0; width: 100%; height: 1px; transform: scaleY(0.5); } .tab-bar-item { flex: 1; text-align: center; display: flex; justify-content: center; align-items: center; flex-direction: column; cover-image { width: 27px; height: 27px; margin-bottom: 12rpx; } cover-view { font-size: 10px; } } } </style>
在所有 tab 页引用
<!-- Application.wpy --> <template> <view> <CustomTabBar selected="0" /> </view> </template> <script> import CustomTabBar from '../components/CustomTabBar'; export default class Application extends wepy.page { components = { CustomTabBar } } </script>
在根目录创建 custom-tab-bar
文件夹,创建 index.wpy
文件。
实际上,根据官方文档指引,应该在
custom-tab-bar
目录下创建.js
、.wxml
、.wxss
和.json
文件。由于项目小程序使用 wepy 框架,所以创建的是.wpy
文件,编译后会生成相应的文件。
<!-- index.wpy --> <template> <cover-view class="tab-bar"> <cover-view class="border"></cover-view> <cover-view wx:for="{{list}}" wx:key="index" class="item" data-path="{{item.pagePath}}" data-index="{{index}}" bindtap="switchTab"> <cover-view wx:if="{{badge[index]}}" class="badge">{{badge[index]}}</cover-view> <cover-image src="{{selected === index ? item.selectedIconPath : item.iconPath}}" /> <cover-view style="color: {{selected === index ? selectedColor : color}}">{{item.text}}</cover-view> </cover-view> </cover-view> </template> <script> // 此处使用的是原生创建组件的方式,保证编译后符合官方推荐的格式。 Component({ data: { badge: {}, selected: 0, color: '#7A7E83', selectedColor: '#6280f5', list: [ { selectedIconPath: '../images/tab_application_pre.png', iconPath: '../images/tab_application.png', pagePath: '/pages/Application', text: '应用' }, { selectedIconPath: '../images/tab_news_pre.png', iconPath: '../images/tab_news.png', pagePath: '/pages/News', text: '新闻' }, { selectedIconPath: '../images/tab_message_pre.png', iconPath: '../images/tab_message.png', pagePath: '/pages/Message', text: '消息' }, { selectedIconPath: '../images/tab_mine_pre.png', iconPath: '../images/tab_mine.png', pagePath: '/pages/MyHome', text: '我的' } ] }, attached () { }, methods: { switchTab (e) { const data = e.currentTarget.dataset const url = data.path wx.switchTab({ url }) this.setData({ selected: data.index }); }, setTabBarBadge(options) { if (!options) return; const { index, text } = options const badge = this.data.badge || {}; badge[index] = text; this.setData({ badge }); }, removeTabBarBadge(options) { if (!options || options.index === undefined) return; const { index } = options; const badge = this.data.badge || {}; badge[index] = null; this.setData({ badge }); } }, }) // NOTE: 此处导出含 config 属性的类,是为了保证编译后生成 .json 文件 export default class CustomTabBar { config = { component: true } } </script> <style lang='less' scoped> .tab-bar { position: fixed; bottom: 0; left: 0; right: 0; background: white; display: flex; padding-top: 16rpx; padding-bottom: env(safe-area-inset-bottom); .border { background-color: rgba(0, 0, 0, 0.33); position: absolute; left: 0; top: 0; width: 100%; height: 1px; transform: scaleY(0.5); } .item { position: relative; flex: 1; text-align: center; display: flex; justify-content: center; align-items: center; flex-direction: column; .badge { position: absolute; top: 0; right: 50%; padding: 4rpx 12rpx; border-radius: 28rpx; font-size: 20rpx; background-color: red; color: #fff; z-index: 3; transform: translateX(100%); } cover-image { width: 27px; height: 27px; margin-bottom: 12rpx; } cover-view { font-size: 10px; } } } </style>
同方案一的步骤一,修改全局配置。
在每个 tab 页中设置 tabBar 的选中状态。
<!-- Application.wpy -->
export default class Application extends wepy.page {
onShow() {
if (this.$wxpage && typeof this.$wxpage.getTabBar === 'function') {
const tabBar = this.$wxpage.getTabBar();
tabBar.setData({
selected: 0, // 由于Application是第一个tab页
});
}
}
}
封装常用操作 tabBar 的方法,包括 tabBar 徽标功能。
// 获取自定义 tabBar 组件示例 export const getCustomTabBar = ctx => { let tabBar = null; if (ctx && ctx.$wxpage && typeof ctx.$wxpage.getTabBar === 'function') { tabBar = ctx.$wxpage.getTabBar(); } return tabBar; }; // 设置 active tabBar export const setActiveTabBar = (ctx, index = 0) => { const tabBar = getCustomTabBar(ctx); if (tabBar) { tabBar.setData({ selected: index }); } }; // 设置徽标 export const setTabBarBadge = (ctx, options = { index: 0, text: '' }) => { const { index = 0, text = '' } = options; const tabBar = getCustomTabBar(ctx); if (tabBar) { tabBar.setTabBarBadge({ index, text }); } else { wx.setTabBarBadge({ index, text }); } }; // 移除徽标 export const removeTabBarBadge = (ctx, options = { index: 0 }) => { const { index = 0 } = options; const tabBar = getCustomTabBar(ctx); if (tabBar) { tabBar.removeTabBarBadge({ index }); } else { wx.removeTabBarBadge({ index }); } };
注意
在自定义 tabBar 模式下
- 为了保证低版本兼容以及区分哪些页面是 tab 页,tabBar 的相关配置项仍然需要完整声明,但这些字段不会作用于自定义 tabBar 的渲染。
- 此时需要开发者提供一个自定义组件来渲染 tabBar,所有 tabBar 的样式都由该自定义组件渲染。推荐用 fixed 在底部的 cover-view + cover-image 组件渲染样式,以保证 tabBar 层级相对较高。
- 与 tabBar 样式相关的接口,如 wx.setTabBarItem 等将失效。
- 每个 tab 页下的自定义 tabBar 组件实例是不同的,可通过自定义组件下的
getTabBar
接口,获取当前页面的自定义 tabBar 组件实例。
注意
如需实现 tab 选中态,要在当前页面下,通过
getTabBar
接口获取组件实例,并调用 setData 更新选中态。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。