首页IT科技uniapp底部导航栏中间凸起(uniapp自定义tabbar(支持中间凸起,角标,动态隐藏tab,全端适用))

uniapp底部导航栏中间凸起(uniapp自定义tabbar(支持中间凸起,角标,动态隐藏tab,全端适用))

时间2025-07-30 20:47:07分类IT科技浏览14128
导读:背景 在使用uniapp进行开发时,tabbar是我们使用的很频繁的一个组件,但是在特定的平台会有一些使用上的限制,无法通过一套代码来做通用平台的适配。比如说中间按钮凸起,动态隐藏某个tab(不同角色展示不同功能),使用字体图标,数字角标等,这些功能不是所有平台都支持。今天我们就用一套代...

背景

在使用uniapp进行开发时                   ,tabbar是我们使用的很频繁的一个组件                          ,但是在特定的平台会有一些使用上的限制          ,无法通过一套代码来做通用平台的适配                   。比如说中间按钮凸起               ,动态隐藏某个tab(不同角色展示不同功能)                          ,使用字体图标               ,数字角标等          ,这些功能不是所有平台都支持                          。今天我们就用一套代码来实现这些功能全端支持          。

思路

实现思路就是通过通过自定义view来实现我们这个tabbar功能                          ,然后页面通过组件来展示               。通过点击不同的tab来显示不同的组件来达到模拟原生tabbar切换效果                          。那有些人要问了                   ,你咋知道我项目中有多少个tab     ,这些tab叫什么名字了?那这里就可以利用uniapp提供的组件easycom模式来解决这些问题                           ,只要我们设置好组件的限制个数和提前占位名称                       ,这些问题就迎刃而解               。

实现

1                  、我们现在components(没有就新建一个components目录)目录下新建一个文件夹(我这里叫ctab),然后分别新建一个vue组件和一个js文件          。组件可以让我们在其他地方引用                       ,js文件主要是做配置                          。

2                             、新建tab组件                           ,我们组件最多限制5个tab组件     ,然后需要通过easycom占位来实现                   ,所以你需要几个tab组件就在components目录下建几个组件命名为ctabx                   。如下所示                          ,我这里要展示三个tab:

特别注意这里的tab组件命名一定要符合easycom规范          ,不然可能会引起组件引用错误     。

这里示例一个ctab1写法: <template> <view style="width: 750rpx;height: 300rpx;background-color: red;"> 首页 </view> </template> <script> export default { name: "ctab1", data() { return {}; }, mounted() {}, methods: {} } </script> <style> </style>

3        、tabbar组件ctab.vue实现               ,这里就直接上代码了                          ,直接copy就能使用               ,关键地方已加上注释

<template> <view> <!--中间按钮凸起模式--> <block v-if="midBtn && midBtn.show"> <!--凸起模式最多展示四个--> <block v-if="tabs.length < 4"> <ctab1 v-show="sindex == 0"></ctab1> <ctab2 v-show="sindex == 2"></ctab2> </block> <block v-else="tabs.length >= 4"> <ctab1 v-show="sindex == 0"></ctab1> <ctab2 v-show="sindex == 1"></ctab2> <ctab3 v-show="sindex == 3"></ctab3> <ctab4 v-show="sindex == 4"></ctab4> </block> <view class="tabbar"> <!--中间按钮凸起模式tab为3个或者5个--> <view class="tab-item" v-for="(item,index) in (tabs.length < 4 ? 3 : 5)" :key="item" @click="handleTabClick(index)"> <!--中间按钮凸起显示图片和文字--> <block v-if="index == floor"> <view :style="bottom: calc(+(midBtn.offset ? midBtn.offset : 50rpx)+ + env(safe-area-inset-bottom));width: +(midBtn.width ? midBtn.width : 150rpx)+;height: +(midBtn.width ? midBtn.width : 150rpx)+;background:+(midBtn.background ? midBtn.background : #ffffff)" class="mid-btn"> <image :src="midBtn.icon" :style="width: +(midBtn.iconwidth ? midBtn.iconwidth : midBtn.width)+;height: +(midBtn.iconheight ? midBtn.iconheight : midBtn.width)+;" @click="handleMidBtn"/> </view> <text class="mid-text" :style="margin-top: +(midBtn.textoffset ? midBtn.textoffset : 50rpx;)" v-show="midBtn.showtext">{{midBtn.text}}</text> </block> <!--普通tab这里需要注意index选择--> <block v-else> <view class="c-tab-item"> <text :class="tab-iconfont iconfont +(tabs[index < floor ? index : index-1].iconfont)" :style="color:+(sindex == index ? scolor : color)" v-if="tabs[index < floor ? index : index-1].iconfont"/> <image :src="sindex == index ? tabs[index < floor ? index : index-1].iconSelect : tabs[index < floor ? index : index-1].icon" class="tab-icon" v-else/> <text class="tab-text" :style="color:+(sindex == index ? scolor : color)">{{tabs[index < floor ? index : index-1].text}}</text> <view class="corner" v-show="tabs[index < floor ? index : index-1].mark > 0">{{tabs[index < floor ? index : index-1].mark > 99 ? 99+ : tabs[index < floor ? index : index-1].mark}}</view> </view> </block> </view> </view> </block> <!--普通模式--> <block v-else> <block v-if="tabs.length == 1"> <ctab1 v-show="sindex == 0 && tabs[0].show"></ctab1> </block> <block v-else-if="tabs.length == 2"> <ctab1 v-show="sindex == 0 && tabs[0].show"></ctab1> <ctab2 v-show="sindex == 1 && tabs[1].show"></ctab2> </block> <block v-else-if="tabs.length == 3"> <ctab1 v-show="sindex == 0 && tabs[0].show"></ctab1> <ctab2 v-show="sindex == 1 && tabs[1].show"></ctab2> <ctab3 v-show="sindex == 2 && tabs[2].show"></ctab3> </block> <block v-else-if="tabs.length == 4"> <ctab1 v-show="sindex == 0 && tabs[0].show"></ctab1> <ctab2 v-show="sindex == 1 && tabs[1].show"></ctab2> <ctab3 v-show="sindex == 2 && tabs[2].show"></ctab3> <ctab4 v-show="sindex == 3 && tabs[3].show"></ctab4> </block> <block v-else-if="tabs.length >= 5"> <ctab1 v-show="sindex == 0 && tabs[0].show"></ctab1> <ctab2 v-show="sindex == 1 && tabs[1].show"></ctab2> <ctab3 v-show="sindex == 2 && tabs[2].show"></ctab3> <ctab4 v-show="sindex == 3 && tabs[3].show"></ctab4> <ctab5 v-show="sindex == 4 && tabs[4].show"></ctab5> </block> <view class="tabbar"> <view class="tab-item" v-for="(item,index) in tabs" :key="item.text" v-show="item.show" @click="handleTabClick(index)"> <view class="c-tab-item"> <text :class="tab-iconfont iconfont +(item.iconfont)" :style="color:+(sindex == index ? scolor : color)" v-if="item.iconfont"/> <image :src="sindex == index ? item.iconSelect : item.icon" class="tab-icon" v-else/> <text class="tab-text" :style="color:+(sindex == index ? scolor : color)">{{item.text}}</text> <view class="corner" v-show="item.mark > 0">{{item.mark > 99 ? 99+ : item.mark}}</view> </view> </view> </view> </block> </view> </template> <script> //读取配置 import ctabbar from ./ctab-config.js export default { name: "ctab", data() { return { tabs: [], color: , scolor: , midBtn: {}, sindex: 0, floor: -1,//midButton开启时使用 } }, mounted() { let tabbar = ctabbar.tabbar this.color = tabbar.color this.scolor = tabbar.selectcolor if(tabbar.midButton && tabbar.midButton.show && tabbar.tabs.length < 2){ throw new Error(midButton模式开启          ,配置tab选项不能少于2个) } if(tabbar.midButton && tabbar.midButton.show){ let mlength = tabbar.tabs.length < 4 ? 3 : 5 this.floor = Math.floor(mlength/2) } //普通模式                          ,设置选中的tab项 let tablen = tabbar.tabs.length if(!tabbar.midButton.show){ if(!tabbar.tabs[0].show){ this.sindex ++ if(tablen >= 2 && !tabbar.tabs[1].show){ this.sindex ++ if(tablen >= 3 && !tabbar.tabs[2].show){ this.sindex ++ if(tablen >= 4 && !tabbar.tabs[3].show){ this.sindex ++ if(tablen >= 5 && !tabbar.tabs[4].show){ throw new Error(tab不能全部隐藏) } } } } } } if(tabbar.tabs.length <= 5){ this.tabs = tabbar.tabs }else { this.tabs = tabbar.tabs.slice(0,5) } this.midBtn = tabbar.midButton }, methods: { setTheme(color){ this.scolor = color this.midBtn.background = color }, //设置tab隐藏和显示                   ,midButton模式失效 setTabVisible(index,visible){ if(this.tabs[index]){ this.tabs[index].show = visible } }, //设置角标 setCorner(index,num){ if(this.tabs[index]){ this.tabs[index].mark = num } }, handleTabClick(tab){ if(this.midBtn && this.midBtn.show){ if(tab == this.floor){ return } } this.sindex = tab let rindex = tab if(this.midBtn && this.midBtn.show){ if(tab > this.floor){ rindex -- } } this.$emit(tabClick,rindex) }, handleMidBtn(){ this.$emit(midClick) } } } </script> <style> /*这里引入字体图标     ,如果使用字体图标的话*/ @import @/common/font/iconfont.css; .tabbar { position: fixed; z-index: 99; width: 100%; height: 100rpx; background-color: #ffffff; bottom: 0; left: 0; box-shadow: 0rpx 4rpx 8rpx 0rpx rgba(0,0,0,0.5); border-radius: 0px 0px 0px 0px; opacity: 1; display: flex; flex-direction: row; align-items: center; justify-content: center; padding-bottom: constant(safe-area-inset-bottom); padding-bottom: env(safe-area-inset-bottom); box-sizing: content-box; } .tab-item { flex: 1; height: 100rpx; display: flex; flex-direction: column; align-items: center; justify-content: center; } .c-tab-item { height: 120rpx; display: flex; flex-direction: column; width: 120rpx; align-items: center; justify-content: center; position: relative; } .tab-icon { width: 45rpx; height: 45rpx; } .tab-iconfont { font-size: 45rpx; font-weight: bold; } .tab-text { font-size: 26rpx; color: #333333; margin-top: 5rpx; } .mid-btn { position: absolute; display: flex; flex-direction: row; justify-content: center; align-items: center; background-color: red; border-radius: 50%; } .mid-text { font-size: 25rpx; color: #999999; } .corner { text-align: center; width: 45rpx; height: 45rpx; position: absolute; background-color: red; border-radius: 50%; color: white; font-size: 20rpx; font-weight: bold; top: 5rpx; right: 0; display: flex; flex-direction: row; justify-content: center; align-items: center; } </style>

4             、配置文件如下:

var tabbar = { /*开启midButton模式时取前两个或者前四个显示                           ,其他忽略*/ midButton: { show: true,//是否是中间凸起模式 width: 153rpx,//不填默认150rpx 中间按钮大小 iconwidth: 67rpx,//不填默认150rpx 中间图标大小 iconheight: 60rpx, offset: 40rpx,//不填默认50rpx background: #F7D456,//中间按钮背景颜色 text: 拍一拍, textoffset: 50rpx,//不填默认50rpx showtext: false, icon: ../../static/tabbar/camera.png }, color: #333333,//未选中颜色 selectcolor: #F7D456,//选中颜色 /*tabs最多5个,超过5个超过的部分会被忽略,show属性用来控制tab显示隐藏                       ,midButton开启时失效,iconfont优先,没有就使用icon*/ tabs: [{ icon: ../../static/tabbar/main_tab_home_normal.png, iconSelect: ../../static/tabbar/main_tab_home_select.png, text: 首页, iconfont: , show: true, mark: 0//角标数量                       ,小于等于0不显示 }, { icon: ../../static/tabbar/main_tab_task_normal.png, iconSelect: ../../static/tabbar/main_tab_task_select.png, text: 任务, iconfont: , show: true, mark: 100 }, { icon: ../../static/tabbar/main_tab_my_normal.png, iconSelect: ../../static/tabbar/main_tab_my_select.png, text: 我的, iconfont: icon-wode,//注意配置字体图标会优先使用字体图标                           ,这里是示例 show: true, mark: 9 }] } module.exports = { tabbar }

5                              、使用示例:

<template> <ctab @midClick=midClick @tabClick=tabClick ref="ctab"/> </template> <script> export default { data() { return { } }, onLoad() { }, methods: { //凸起按钮点击事件 midClick(){ console.log(midClick) }, //tab切换点击事件 tabClick(tab){ console.log(tabClick,tab) } } } </script> <style> page { width: 100%; height: 100%; } </style>

6             、到这里我们自定义tabbar就完成了     ,通过修改配置文件中的midButton中的show属性来开启是否中间按钮凸起                   ,接下来我们看下效果                           。

midButton开启:

普通模式:

再普通模式下                          ,我们可以通过配置或者动态修改tabs中tab obj中的show属性来动态形式和隐藏某个tab          ,我们这里配置第一个tab为隐藏: ... tabs: [{ icon: ../../static/tabbar/main_tab_home_normal.png, iconSelect: ../../static/tabbar/main_tab_home_select.png, text: 首页, iconfont: , show: false,//隐藏第一个tab mark: 0//角标数量               ,小于等于0不显示 }, { icon: ../../static/tabbar/main_tab_task_normal.png, iconSelect: ../../static/tabbar/main_tab_task_select.png, text: 任务, iconfont: , show: true, mark: 100 }, { icon: ../../static/tabbar/main_tab_my_normal.png, iconSelect: ../../static/tabbar/main_tab_my_select.png, text: 我的, iconfont: , show: true, mark: 9 }] ...

效果图如下:

7        、到这里我们的自定义tabbar就完成了                          ,剩下的就是在tab组件中实现我们各个页面的逻辑                       。我们通过配置文件可以轻松的使用一个套代码实现tabbar中间按钮凸起                             、数字角标                  、动态隐藏    、自定义mask覆盖tabbar(需要自己控制好层级)               ,字体图标等功能          ,并且全端适用。

尾巴

本次内容就这么多                          ,欢迎给我点赞和关注                   ,有什么疑问欢迎给我留言     ,谢谢!

声明:本站所有文章                           ,如无特殊说明或标注                       ,均为本站原创发布                       。任何个人或组织,在未征得本站同意时                       ,禁止复制                            、盗用                       、采集、发布本站内容到任何网站                       、书籍等各类媒体平台                           。如若本站内容侵犯了原著者的合法权益                           ,可联系我们进行处理     。

创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!

展开全文READ MORE
python爬取代理ip(【Python】爬虫实战-基于代理池的高并发爬虫) 网站建设的内容是什么(网站建设的常见要素)