uniapp自定義tabbar的方法(支持中間凸起、角標、動態(tài)隱藏tab和全端適用)
背景
在使用uniapp進行開發(fā)時,tabbar是我們使用的很頻繁的一個組件,但是在特定的平臺會有一些使用上的限制,無法通過一套代碼來做通用平臺的適配。比如說中間按鈕凸起,動態(tài)隱藏某個tab(不同角色展示不同功能),使用字體圖標,數(shù)字角標等,這些功能不是所有平臺都支持。今天我們就用一套代碼來實現(xiàn)這些功能全端支持。
思路
實現(xiàn)思路就是通過通過自定義view來實現(xiàn)我們這個tabbar功能,然后頁面通過組件來展示。通過點擊不同的tab來顯示不同的組件來達到模擬原生tabbar切換效果。那有些人要問了,你咋知道我項目中有多少個tab,這些tab叫什么名字了?那這里就可以利用uniapp提供的組件easycom模式來解決這些問題,只要我們設置好組件的限制個數(shù)和提前占位名稱,這些問題就迎刃而解。
實現(xiàn)
1、我們現(xiàn)在components(沒有就新建一個components目錄)目錄下新建一個文件夾(我這里叫ctab),然后分別新建一個vue組件和一個js文件。組件可以讓我們在其他地方引用,js文件主要是做配置。
2、新建tab組件,我們組件最多限制5個tab組件,然后需要通過easycom占位來實現(xiàn),所以你需要幾個tab組件就在components目錄下建幾個組件命名為ctabx。如下所示,我這里要展示三個tab:
特別注意這里的tab組件命名一定要符合easycom規(guī)范,不然可能會引起組件引用錯誤。
這里示例一個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實現(xiàn),這里就直接上代碼了,直接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優(yōu)先,沒有就使用icon*/ tabs: [{ icon: '../../static/tabbar/main_tab_home_normal.png', iconSelect: '../../static/tabbar/main_tab_home_select.png', text: '首頁', iconfont: '', show: true, mark: 0//角標數(shù)量,小于等于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',//注意配置字體圖標會優(yōu)先使用字體圖標,這里是示例 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開啟:
普通模式:
再普通模式下,我們可以通過配置或者動態(tài)修改tabs中tab obj中的show屬性來動態(tài)形式和隱藏某個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//角標數(shù)量,小于等于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組件中實現(xiàn)我們各個頁面的邏輯。我們通過配置文件可以輕松的使用一個套代碼實現(xiàn)tabbar中間按鈕凸起、數(shù)字角標、動態(tài)隱藏、自定義mask覆蓋tabbar(需要自己控制好層級),字體圖標等功能,并且全端適用。
尾巴
到此這篇關于uniapp自定義tabbar的文章就介紹到這了,更多相關uniapp自定義tabbar內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Bootstrap CSS組件之下拉菜單(dropdown)
這篇文章主要為大家詳細介紹了Bootstrap CSS組件之下拉菜單(dropdown),具有一定的參考價值,感興趣的小伙伴們可以參考一下2016-12-12Layui彈框中數(shù)據(jù)表格中可雙擊選擇一條數(shù)據(jù)的實現(xiàn)
這篇文章主要介紹了Layui彈框中數(shù)據(jù)表格中可雙擊選擇一條數(shù)據(jù)的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-05-05javascript中導出與導入實現(xiàn)模塊化管理教程
這篇文章主要給大家介紹了關于javascript中導出與導入實現(xiàn)模塊化管理的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-12-12window.location和document.location的區(qū)別分析
用戶不能改變document.location(因為這是當前顯示文檔的位置)。但是,可以改變window.location (用其它文檔取代當前文檔)window.location本身也是一個對象,而document.location不是對象2008-12-12safari,opera嵌入iframe頁面cookie讀取問題解決方法
最近做的合作網(wǎng)站嵌入到對方的iframe中去,在safari,opera和有些版本的搜狗瀏覽器(內(nèi)核版本原因)中不能讀到cookie。2010-06-06Leaflet?數(shù)據(jù)可視化實現(xiàn)地圖下鉆示例詳解
這篇文章主要為大家介紹了Leaflet數(shù)據(jù)可視化實現(xiàn)地圖下鉆示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-01-01