最近有不少微信開發者朋友在QQ上加我好友,突然意識到你們對微信自定義底部導航欄需求仍是挺大的,故而再次整理下底部導航欄組件開發思路。和以前的文章仍是有些區別,而且底部導航欄組件增長新的特性以及一些優化開發體驗的騷操做。css
與以前不一樣,如今咱們有兩種方法實現自定義底部導航欄,由於小程序在2.5.0開始支持自定義底部導航欄了戳此處看文檔,因此咱們如今的可選方案爲:html
HideTabBar
接口hack底部導航欄下面根據兩種方式都講講git
HideTabBar
接口hack底部導航欄首先咱們先了解下微信的路由api和微信的路由機制,微信一共提供了5個路由api:wx.navigateTo
、wx.redirectTo
、wx.switchTab
、wx.navigateBack
、wx.reLaunch
,具體文檔位於https://developers.weixin.qq.com/miniprogram/dev/api/ui-navigate.html。github
其中咱們用哪一個呢?很顯然wx.switchTab
很合咱們的口味,由於他的切換效果是沒有推入推出動畫的,更符合咱們的習慣,那使用他的前提是咱們須要在app.json
文件中配置tabBar
屬性,而只要一配置了tabBar
屬性,系統原生的導航欄就出現了,幸虧微信有一個隱藏原生導航欄的api:wx.hideTabBar。看到這裏相信聰明的同窗已經知道了實現思路,就是隱藏掉原生的而後本身去實現一個導航欄貼在最下面。json
源碼地址小程序
本次代碼拷貝以後能夠直接使用,具體操做以下微信小程序
在app.json中設置usingComponents
對象api
在tab頁面的wxml最後追加<custom-tab-bar></custom-tab-bar>
微信
便可觀察效果微信開發
app.json
中tabBar
的配置wx.showTabBarRedDot
方法能夠設置紅點看過之間博客的同窗知道,以前是須要一個額外的route.js文件的,來獲取tabBar的配置,緣由是小程序js沒法讀取json文件。隨着知(sao)識(cao zuo)掌握增多,發現了更加方便的辦法:咱們能夠經過__wxConfig
全局對象的tabBar
屬性去查看app.json
設置。因此咱們在組件中直接這樣定義:
const fixListConfig = function(item, index) { const result = {}; // 使用新對象,相似淺拷貝 result.pagePath = "/" + item.pagePath.replace(/.html$/g, ""); result.iconPath = item.iconData ? "data:image/png;base64," + item.iconData : "/" + item.iconPath; result.selectedIconPath = item.selectedIconData ? "data:image/png;base64," + item.selectedIconData : "/" + item.selectedIconPath; result.idx = index; result.redDot = false; result.text = item.text; return result; }; const _tabBar = __wxConfig.tabBar; Component({ data: { activeIdx: -1, config: _tabBar, list: _tabBar.list.map(fixListConfig) }, });
其中list
就是咱們tab頁面列表,tabBar
裏面還包括了咱們定義的一些樣式,好比selectColor
之類的,由於格式並非直接拿來就能用,因此咱們用map對數據進行了修改和淺拷貝。
此處還有一個坑,部分真機上小程序配置中的圖標會變成base64格式的,因此須要作兼容。
上面代碼不是難點,關鍵在於__wxConfig
對象,你們能夠在微信開發工具控制檯執行this.__wxConfig
看看裏面的內容,相信能對你有所啓發。
相信你們都用過getCurrentPages()
這個全局函數,咱們也是經過它來獲取當前頁面的路由而後將其標記爲active
狀態。本着本身的事情本身作的原則,我利用自定義組件的pageLifetimes
功能,實現了內部判斷當前頁,具體代碼以下:
pageLifetimes: { show() { const pages = getCurrentPages(); const page = pages[pages.length - 1]; const route = page.__route__; const idx = this.data.list.find(item => item.pagePath === `/${route}`) .idx; if (this.data.activeIdx !== idx) { this.setData({ activeIdx: idx }); } } }
注意pageLifetimes
特性在基礎庫2.2.3以上支持,目前沒什麼問題,其實外面傳值寫死也是ok的,畢竟每一個頁面是一個單獨的組件。
此處一需一行代碼
.tab-bar{ padding-bottom: env(safe-area-inset-bottom); }
這個方法不光可用於小程序,也可用於移動端,網上有不少介紹他的文章,好比網頁適配 iPhoneX,就是這麼簡單
上面特性中提到了,咱們可使用wx.showTabBarRedDot
方法設置咱們的redDot,也能夠打開上面的小程序微碼查看效果。這個是利用Object.defineProperty
方法實現的,具體代碼能夠看custom-tab-bar/extraFun.js
文件查看。這塊就再也不詳述了,你們想了解的能夠直接閱讀源碼,若是有疑問能夠單獨聯繫我。
如今,咱們來聊聊爲何不用小程序支持的配置方法實現底部導航欄。
如今咱們根據文檔進行改造,在app.json
的tabBar
對象中增長"custom":true
,並在根目錄下增長custom-tab-bar/index
組件。以後的開發就和上面差很少了,咱們寫組件實現指望的效果。
爲了描述方便,咱們將以前提到的方法稱爲方法一,小程序配置的稱之爲方法二。方法一的組件是在page裏面的,方法二的組件是和page並列的關係,如圖所示:
這個對咱們有什麼影響嗎,就我目前觀察,有幾個問題
addGlobalClass
選項以後(不瞭解addGlobalClass
的同窗見文檔:使組件接受全局樣式)最後仍是感謝你們能堅持讀完,本人做爲一個理科生,文筆太差,有許多想法表達不出來,真是吃了沒文化的虧。文中介紹的兩種方法,我目前仍是隻會考慮第一種,之後會一直觀望微信配置法,相信當它完善的那天我會堅決果斷的使用,畢竟跟着標準才能走的更遠。若是對本代碼或在開發過程當中遇到什麼問題,歡迎與我交流858582381~
另外,下一步打算分享自定義頭部標題欄,不知道你們對此是否期待。