再談小程序自定義底部導航

小程序自定義tabBar再探索

前言

最近有不少微信開發者朋友在QQ上加我好友,突然意識到你們對微信自定義底部導航欄需求仍是挺大的,故而再次整理下底部導航欄組件開發思路。和以前的文章仍是有些區別,而且底部導航欄組件增長新的特性以及一些優化開發體驗的騷操做。css

技術選型

與以前不一樣,如今咱們有兩種方法實現自定義底部導航欄,由於小程序在2.5.0開始支持自定義底部導航欄了戳此處看文檔,因此咱們如今的可選方案爲:html

  • 經過HideTabBar接口hack底部導航欄
  • 經過小程序支持配置實現底部導航欄

下面根據兩種方式都講講git

經過HideTabBar接口hack底部導航欄

實現思路

首先咱們先了解下微信的路由api和微信的路由機制,微信一共提供了5個路由api:wx.navigateTowx.redirectTowx.switchTabwx.navigateBackwx.reLaunch,具體文檔位於https://developers.weixin.qq.com/miniprogram/dev/api/ui-navigate.htmlgithub

其中咱們用哪一個呢?很顯然wx.switchTab很合咱們的口味,由於他的切換效果是沒有推入推出動畫的,更符合咱們的習慣,那使用他的前提是咱們須要在app.json文件中配置tabBar屬性,而只要一配置了tabBar屬性,系統原生的導航欄就出現了,幸虧微信有一個隱藏原生導航欄的api:wx.hideTabBar。看到這裏相信聰明的同窗已經知道了實現思路,就是隱藏掉原生的而後本身去實現一個導航欄貼在最下面。json

使用方法

源碼地址小程序

本次代碼拷貝以後能夠直接使用,具體操做以下微信小程序

  1. 複製components/custom-tab-bar文件夾到你的項目
  2. 在app.json中設置usingComponents對象api

  3. 在tab頁面的wxml最後追加<custom-tab-bar></custom-tab-bar>微信

便可觀察效果微信開發

支持的特性

  • 無需額外配置,甚至不用傳參,自動讀取app.jsontabBar的配置
  • 使用wx.showTabBarRedDot方法能夠設置紅點
  • 能夠自定義樣式,擺脫微信限制(如borderStyle僅支持black/white的限制)
  • 能夠定製個性化邏輯
  • 兼容iphoneX,底部自動留空

關鍵代碼介紹

tabBar配置的獲取

看過之間博客的同窗知道,以前是須要一個額外的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的,畢竟每一個頁面是一個單獨的組件。

使用css兼容iPhone X(強烈建議瞭解)

此處一需一行代碼

.tab-bar{
    padding-bottom: env(safe-area-inset-bottom);
}

這個方法不光可用於小程序,也可用於移動端,網上有不少介紹他的文章,好比網頁適配 iPhoneX,就是這麼簡單

修改wx接口注入本身的代碼邏輯

上面特性中提到了,咱們可使用wx.showTabBarRedDot方法設置咱們的redDot,也能夠打開上面的小程序微碼查看效果。這個是利用Object.defineProperty方法實現的,具體代碼能夠看custom-tab-bar/extraFun.js文件查看。這塊就再也不詳述了,你們想了解的能夠直接閱讀源碼,若是有疑問能夠單獨聯繫我。

經過小程序支持配置實現底部導航欄

如今,咱們來聊聊爲何不用小程序支持的配置方法實現底部導航欄。

使用方法

如今咱們根據文檔進行改造,在app.jsontabBar對象中增長"custom":true,並在根目錄下增長custom-tab-bar/index組件。以後的開發就和上面差很少了,咱們寫組件實現指望的效果。

二者的區別

爲了描述方便,咱們將以前提到的方法稱爲方法一,小程序配置的稱之爲方法二。方法一的組件是在page裏面的,方法二的組件是和page並列的關係,如圖所示:

這個對咱們有什麼影響嗎,就我目前觀察,有幾個問題

  • 某些狀況下會引發bug,當咱們打開一個非tab頁面的時候,仍是會顯示底部導航欄。(最嚴重問題,會有bug)
  • 沒法使用全局定義的樣式,哪怕組件激活了addGlobalClass選項以後(不瞭解addGlobalClass的同窗見文檔:使組件接受全局樣式
  • 須要基礎庫>=2.5.0,有部分用戶沒法覆蓋。當前版本分佈狀況

總結

最後仍是感謝你們能堅持讀完,本人做爲一個理科生,文筆太差,有許多想法表達不出來,真是吃了沒文化的虧。文中介紹的兩種方法,我目前仍是隻會考慮第一種,之後會一直觀望微信配置法,相信當它完善的那天我會堅決果斷的使用,畢竟跟着標準才能走的更遠。若是對本代碼或在開發過程當中遇到什麼問題,歡迎與我交流858582381~

另外,下一步打算分享自定義頭部標題欄,不知道你們對此是否期待。

相關文章
相關標籤/搜索