【愚公系列】2022年09月 微信小程序-自定义tabBar的实现
2023-06-13 09:11:15 时间
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
前言
一、自定义tabBar的实现
1.全局配置
2.主页面
3.CustomTabBar组件
4.效果
前言
小程序自带的tabBar可以参考这篇文章:https://codeboy.blog.csdn.net/article/details/123040278
因为小程序自带的tabBar,比较单一,无法满足多样化需求,这样就需要自己自定义tabBar。
一、自定义tabBar的实现
1.全局配置
全局app.json配置文件禁用自带tabBa
"tabBar": {
"custom": false,
"list": [
{
"pagePath": "pages/index",
"iconPath": "components/custom-tab-bar/component.png",
"selectedIconPath": "components/custom-tab-bar/component-on.png",
"text": "首页"
},
{
"pagePath": "pages/index2",
"iconPath": "components/custom-tab-bar/component.png",
"selectedIconPath": "components/custom-tab-bar/component-on.png",
"text": "首页2"
},
{
"pagePath": "pages/index3",
"iconPath": "components/custom-tab-bar/component.png",
"selectedIconPath": "components/custom-tab-bar/component-on.png",
"text": "自定义"
}
]
}
2.主页面
<!--miniprogram/pages/3.10/custom/index.wxml-->
<text>我是自定义组件l</text>
<CustomTabBar index="0" bindpagenavigating="onPageNavigating"></CustomTabBar>
// miniprogram/pages/3.12/index.js
Page({
/**
* 页面的初始数据
*/
data: {
initData:{}
},
async onPageNavigating(e){
let res = await wx.wxp.request({
url: 'http://localhost:3000/hi?name=index2',
})
e.detail.eventCallback({
openType:"initData",
openData:{
a:res.data
}
})
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
const eventChannel = this.getOpenerEventChannel()
if (eventChannel.on){
eventChannel.on('initData', (data)=> {
console.log("data",data)
this.setData({
initData:data
})
})
}
},
})
3.CustomTabBar组件
iconfont.wxss
@keyframes icon-spin {
0% {
-webkit-transform: rotate(0);
transform: rotate(0);
}
100% {
-webkit-transform: rotate(359deg);
transform: rotate(359deg);
}
}
.iconfont-spin {
-webkit-animation: icon-spin 2s infinite linear;
animation: icon-spin 2s infinite linear;
display: inline-block;
}
.iconfont-pulse {
-webkit-animation: icon-spin 1s infinite steps(8);
animation: icon-spin 1s infinite steps(8);
display: inline-block;
}
.cu-icon-font{
font-family:"iconfont" !important;
font-size:inherit;
font-style:normal;
}
index.js
Component({
behaviors: [require('../../lib/event-behavior.js')],
properties: {
index: {
type: Number,
value: 0
}
},
data: {
selected: 0,
list: [{
pagePath: "/pages/3.12/index",
iconPath: "/components/custom-tab-bar/component.png",
selectedIconPath: "/components/custom-tab-bar/component-on.png",
text: "index",
iconClass:"icon-homefill",
iconTopClass:""
}, {
pagePath: "/pages/3.12/index2/index",
iconPath: "/components/custom-tab-bar/component.png",
selectedIconPath: "/components/custom-tab-bar/component-on.png",
text: "index",
iconClass:"cu-btn icon-add bg-green shadow",
iconTopClass:"add-action"
},{
pagePath: "/pages/3.12/index3/index",
iconPath: "/components/custom-tab-bar/component.png",
selectedIconPath: "/components/custom-tab-bar/component-on.png",
text: "自定义",
iconClass:"icon-my",
iconTopClass:""
}]
},
observers: {
"index": function (id) {
this.setData({ selected: id});
}
},
methods: {
async goToTab(e){
let targetPageUrl = e.currentTarget.dataset.url
// 派发一个事件,让外部业务代码处理,待处理完了,再回到这里
let pageData = await this.triggerWaitingEvent("pagenavigating", {
targetPageUrl
})
let res = await wx.wxp.navigateTo({
url:targetPageUrl
})
if (res.eventChannel){
res.eventChannel.emit(pageData.openType, pageData.openData)
}
}
}
})
event-behavior.js
// 派发一个等待处理,需要有代码处理的事件
module.exports = Behavior({
definitionFilter(defFields) {
defFields.methods.triggerWaitingEvent = function (type, data = {}){
return new Promise((resolve,reject)=>{
let eventCallback = res => resolve(res)
Object.assign(data, {
eventCallback
})
this.triggerEvent(type, data)
})
}
},
})
index.wxml
<view class="tabBar">
<view class="tabbg"></view>
<view class="cu-bar tabbar">
<view wx:for="{{list}}" wx:for-item="item" wx:key="index" class="action {{item.iconTopClass}} {{selected == index?'text-green':''}}" catchtap='goToTab' data-url="{{item.pagePath}}" data-path="{{item.pagePath}}" data-index="{{index}}">
<view class='iconf {{item.iconClass}}'></view>
<view>{{item.text}}</view>
</view>
</view>
</view>
index.wxss
@import './iconfont.wxss';
.tabbg{
background: rgba(255,255,255,1);
width: 100%;
height: 100rpx;
position: absolute;
bottom: 0;
box-shadow: 0 1rpx 6rpx rgba(0, 0, 0, 0.1);
}
.iconf {
font-family: "iconfont" !important;
font-size: inherit;
font-style: normal;
}
.tabBar{
width:100%;
position: fixed;
bottom:0;
font-size:20rpx;
color:#8A8A8A;
}
.text-green{
color: #39b54a;
}
.shadow {
box-shadow: 0 1rpx 6rpx rgba(0, 0, 0, 0.1);
}
.bg-red {
background-color: #e54d42;
color: #fff;
}
.bg-orange {
background-color: #f37b1d;
color: #fff;
}
.bg-yellow {
background-color: #fbbd08;
color: #333;
}
.bg-olive {
background-color: #8dc63f;
color: #fff;
}
.bg-green {
background-color: #39b54a;
color: #fff;
}
.bg-cyan {
background-color: #1cbbb4;
color: #fff;
}
.bg-blue {
background-color: #0081ff;
color: #fff;
}
.bg-purple {
background-color: #6739b6;
color: #fff;
}
.bg-mauve {
background-color: #9c26b0;
color: #fff;
}
.bg-pink {
background-color: #e03997;
color: #fff;
}
.bg-brown {
background-color: #a5673f;
color: #fff;
}
.bg-grey {
background-color: #8799a3;
color: #fff;
}
.bg-gray {
background-color: #f0f0f0;
color: #666;
}
.bg-black {
background-color: #333;
color: #fff;
}
.bg-white {
background-color: #fff;
color: #666;
}
.shadow .bg-green {
box-shadow: 6rpx 6rpx 8rpx rgba(48, 156, 63, 0.2);
}
.cu-bar.tabbar .action.add-action .icon-add {
position: absolute;
width: 70rpx;
z-index: 2;
height: 70rpx;
border-radius: 50%;
line-height: 70rpx;
font-size: 50rpx;
top: -35rpx;
left: 0;
right: 0;
margin: auto;
padding: 0;
}
.cu-bar.tabbar .action.add-action::after {
content: "";
position: absolute;
width: 100rpx;
height: 100rpx;
top: -50rpx;
left: 0;
right: 0;
margin: auto;
box-shadow: 0 -3rpx 8rpx rgba(0, 0, 0, 0.08);
border-radius: 50rpx;
background-color: rgba(255, 255, 255, 1);
z-index: 0;
}
.cu-bar.tabbar .action.add-action::before {
content: "";
position: absolute;
width: 100rpx;
height: 30rpx;
bottom: 30rpx;
left: 0;
right: 0;
margin: auto;
background-color: inherit;
z-index: 1;
}
.cu-btn {
position: relative;
display: inline-flex;
align-items: center;
justify-content: center;
box-sizing: border-box;
padding: 0 30rpx;
font-size: 28rpx;
height: 64rpx;
line-height: 1;
text-align: center;
text-decoration: none;
overflow: visible;
margin-left: initial;
transform: translate(0rpx, 0rpx);
margin-right: initial;
}
.cu-btn::after {
display: none;
}
.cu-bar {
display: flex;
position: relative;
align-items: center;
min-height: 100rpx;
justify-content: space-between;
background: rgba(0,0,0,0);
}
.cu-bar .action {
display: flex;
align-items: center;
height: 100%;
justify-content: center;
max-width: 100%;
}
.cu-bar.tabbar .action .icon-add {
width: 100rpx;
position: relative;
display: block;
height: auto;
margin: 0 auto 10rpx;
text-align: center;
font-size: 40rpx;
}
/* safe-area-inset-*由四个定义了视口边缘内矩形的 top, right, bottom 和 left 的环境变量组成,这样可以安全地放入内容。 */
.cu-bar.tabbar {
padding: 0;
z-index: 0;
height: calc(130rpx + env(safe-area-inset-bottom) / 2);
padding-bottom: calc(env(safe-area-inset-bottom) / 2);
}
.cu-bar {
margin-top: 20rpx;
}
.cu-bar .action:first-child {
margin-left: 30rpx;
font-size: 30rpx;
}
.cu-bar.tabbar .action {
font-size: 22rpx;
position: relative;
flex: 1;
text-align: center;
padding: 0;
display: block;
height: auto;
line-height: 1;
margin: 0;
background-color: inherit;
overflow: initial;
padding-top: 30rpx;
}
.cu-bar.tabbar .action.add-action {
position: relative;
z-index: 2;
padding-top: 0;
}
.icon-homefill {
width: 100rpx;
position: relative;
display: block;
height: auto;
margin: 0 auto 10rpx;
text-align: center;
font-size: 40rpx;
}
.icon-add {
width: 100rpx;
position: relative;
display: block;
height: auto;
margin: 0 auto 10rpx;
text-align: center;
font-size: 40rpx;
}
.icon-my {
width: 100rpx;
position: relative;
display: block;
height: auto;
margin: 0 auto 10rpx;
text-align: center;
font-size: 40rpx;
}
.icon-homefill:before { content: "\e6bb"; }
.icon-my:before { content: "\e78b"; }
.icon-add:before { content: "\e6da";
4.效果
相关文章
- 微信小程序调用摄像头实现拍照功能
- 微信小程序官方组件展示之表单组件textarea源码
- 【愚公系列】2022年09月 微信小程序-电商项目-商品列表也功能实现(待写勿看)
- 微信小程序长按事件
- 【说站】微信天气预报小程序
- 【说站】云开发谁是卧底线下小游戏发牌助手微信小程序源码
- 【说站】微信小程序去水印源码 上传即可使用带流量主功能
- 【愚公系列】2022年08月 微信小程序-自定义导航栏功能的实现
- 【愚公系列】2022年09月 微信小程序-图片裁剪功能实现
- 【愚公系列】2022年09月 微信小程序-图片懒加载功能实现
- php实现微信小程序消息通知「建议收藏」
- 微信小程序+PHP实现登录注册(手把手教程)[通俗易懂]
- 805-Air724UG模块(4G全网通GPRS开发)-微信小程序扫码绑定Air724,并通过MQTT实现远程查看摄像头图像(自建MQTT服务器)
- 【愚公系列】2022年09月 微信小程序-电商项目-商品列表也功能实现12
- 微信小程序官方组件展示之媒体组件video源码
- 微信小程序自动化实现:Automator
- 【愚公系列】2022年10月 微信小程序-电商项目-微信支付后端功能实现(node版)
- 【愚公系列】2022年10月 微信小程序-电商项目-小微商户支付后端功能实现(node版)
- 【愚公系列】2022年10月 微信小程序-电商项目-小微商户支付后端功能实现(node版)
- 模仿Android微信小程序,实现小程序独立任务视图的效果
- 微信小程序宠物论坛4
- 微信小程序—-全局变量「建议收藏」
- 【愚公系列】2022年11月 微信小程序-优购电商项目-授权页面
- 【愚公系列】2022年11月 微信小程序-优购电商项目-搜索页面
- 如何实现自有App上的小程序第三方微信授权登陆?
- 微信小程序 内容评论-回复评论-回复回复的实现
- 微信小程序模板消息接口下线了,不用慌,调用统一服务消息接口来实现相同功能
- 2-STM32+Air724UG基本控制篇(自建物联网平台)-整体运行测试-微信小程序扫码绑定Air724,并通过MQTT和模组实现远程通信控制(使用模组自带MQTT命令)
- 在微信小程序上做一个「博客园年度总结」:后端部分
- 微信小程序+SpringBoot实现文件上传与下载
- 微信小程序直播开发实战
- 微信小程序之跨界面传参详解手机开发