微信小程序自定義組件實現 tabBar、navBar

久不寫文,手有些生,見諒。

最近App項目要將其中一個模塊抽出來做成小程序,
功能包含 :底部的Tab欄頂部的標題欄

這裏選擇自定義的原因有兩點:

  • narBar 微信原生不支持設置返回圖標,且在 Android 上標題是居左顯示,在 iOS 上是居中顯示。
  • 底部的 tabBar 不支持點擊跳頁面,圖標佈局不支持超過 tabBar 的高度。

下面兩張圖是簡單實現的效果。


實現分析
源碼地址

實現分析

以上效果我也是參考的網上例子來實現,可看該效果原作的分析。或者看看下面我的理解。

微信小程序自定義組件

官方文檔地址 https://developers.weixin.qq.com/miniprogram/dev/framework/custom-component/

文檔中說明了自定義組件

  • 可以將頁面內的功能模塊抽象成自定義組件,以便在不同的頁面中重複使用。
  • 也可以將複雜的頁面拆分成多個低耦合的模塊,有助於代碼維護。

創建自定義組件

在最新的開發工具中已經支持直接創建組件了,創建一個 components目錄,然後在創建一個組件對於的目錄,例如這裏創建的是tabbar目錄,然後在該目錄點擊鼠標右鍵選擇新建Component,輸入組件名稱即可,例如這裏輸入的是tabbar

組件模板和樣式

官方文檔 https://developers.weixin.qq.com/miniprogram/dev/framework/custom-component/wxml-wxss.html

類似於頁面,自定義組件擁有自己的wxml 模板和 wxss 樣式

在組件模板中可以提供一個<slot>節點,用於承載組件引用時提供的子節點。這個<slot>節點相當於組件佔位符。

默認情況wxml中只支持一個<solt>節點,可以設置支持多個<solt>節點:

佈局編寫好之後就開始設置樣式了,在頁面中可以通過wxss來定義,也可以通過設置組件的class名稱,然後再調用該組件的 wxss中定義樣式。


組件的wxss默認是不支持app.wxss樣式的,但是可以像設置多<slot>一樣,進行設置:

模板數據綁定

通過調用 Component構造器時可以指定組件的屬性、數據、方法等。https://developers.weixin.qq.com/miniprogram/dev/framework/custom-component/component.html

Component({
  // 詳細使用看文檔
  behaviors: [],

  properties: {
    myProperty: { // 屬性名
      type: String, // 類型(必填),目前接受的類型包括:String, Number, Boolean, Object, Array, null(表示任意類型)
      value: '', // 屬性初始值(可選),如果未指定則會根據類型選擇一個
      observer(newVal, oldVal, changedPath) {
        // 屬性被改變時執行的函數(可選),也可以寫成在methods段中定義的方法名字符串, 如:'_propertyChange'
        // 通常 newVal 就是新設置的數據, oldVal 是舊數據
      }
    },
    myProperty2: String // 簡化的定義方式
  },
  data: {}, // 私有數據,可用於模板渲染

  lifetimes: {
    // 生命週期函數,可以爲函數,或一個在methods段中定義的方法名
    attached() { },
    moved() { },
    detached() { },
  },

  // 生命週期函數,可以爲函數,或一個在methods段中定義的方法名
  attached() { }, // 此處attached的聲明會被lifetimes字段中的聲明覆蓋
  ready() { },

  pageLifetimes: {
    // 組件所在頁面的生命週期函數
    show() { },
    hide() { },
    resize() { },
  },

  methods: {
    onMyButtonTap() {
      this.setData({
        // 更新屬性和數據的方法與更新頁面數據的方法類似
      })
    },
    // 內部方法建議以下劃線開頭
    _myPrivateMethod() {
      // 這裏將 data.A[0].B 設爲 'myPrivateData'
      this.setData({
        'A[0].B': 'myPrivateData'
      })
    },
    _propertyChange(newVal, oldVal) {

    }
  }

})

在上面的代碼中我們可以通過propertiessetData結合實現動態設置數據,在methods中可以定義方法,用於給外部調用,也就是組件間的通信。

組件間通信

可以通過triggerEvent或者直接獲取組件this.selectComponent示例來調用方法和屬性。

  • triggerEvent
  • 父組件還可以通過 this.selectComponent 方法獲取子組件實例對象,這樣就可以直接訪問組件的任意數據和方法。

開始使用組件

在頁面的json文件中配置組件的路徑,如下:

{
  "usingComponents": {
    "navbar": "/components/navbar/index",
    "tabbar": "/components/tabbar/tabbar"
  }
}

在頁面的wxml佈局中添加,如下:

// 引入組件
<navbar navbar-data='{{nvabarData}}'></navbar>
// 內容
<view class="home-page">
  <view style='margin-top: {{height}}px;margin-bottom:10px;'></view>
</view>
// 引入組件
<tabbar tabbar="{{tabbar}}"></tabbar>

自定義 tabBar 組件分析

看文章頂部原作者的分析。下面介紹一些坑。

  • 雖然在組件的js文件中已經設置了tabbar 但是在app.json中還是需要配置tabbar,詳細配置可看文章頂部github鏈接。

  • 在頁面的onload中還需要再設置一次

wx.hideTabBar({
    })

因爲從分享頁面點擊左上角的首頁圖標回到首頁會出現兩個tabbar,所以在首頁還需要再隱藏一次tabbar.

  • 注意路徑問題,新版的開發工具components文件應該在miniprogram下,和pages爲同級,否則在引入組件的路徑中可能會出錯。

自定義 navBar 組件分析

小程序中分享出去的頁面是沒有返回按鈕的,爲了用戶能夠再次回到我們的小程序中,我們在 navbar 上自定義了一個返回按鈕和返回首頁的按鈕。

這裏通過小程序的場景值和使用一個全局的變量share來判斷是否是從分享頁面進來。在 app.js中做了處理:

// 判斷是否由分享進入小程序
    if (options.scene == 1007 || options.scene == 1008) {
      this.globalData.share = true
    } else {
      this.globalData.share = false
    };

爲了適配頂部的高度,在wxml佈局中還動態設置了一個margin-top的高度,這個高度通過獲取系統的狀態欄高度得到。

 getSystemInfo: function () {
    let t = this;
    wx.getSystemInfo({
      success: function (res) {
        // 獲取高度
        t.globalData.height = res.statusBarHeight;
      }
    });
  },

然後在頁面的data中設置組件的數據和狀態欄的高度:

data: {
    // 組件所需的參數
    nvabarData: {
      showCapsule: 0, //是否顯示左上角圖標   1表示顯示    0表示不顯示
      title: '讓故事發生', //導航欄 中間的標題
    },
    // 此頁面 頁面內容距最頂部的距離
    height: app.globalData.height * 2 + 20,
    // tabbar
    tabbar: {},
  },

原作者在實現圖標的顯示和隱藏部分邏輯和我的預期不一致,我想實現的是從分享頁面進入才顯示左上角的返回首頁圖標,正常也就只顯示返回按鈕。修改點後的wxml如下:

      <view bindtap='_navback' wx:if='{{!share}}'>
        <image src='/images/back.png' mode='aspectFill' class='back-pre'></image>
      </view>
// 這裏把 share 取反去掉
      <view class='navbar-v-line' wx:if='{{share}}'></view>
// 這裏把  share 取反去掉
      <view bindtap='_backhome'  wx:if='{{share}}'>
        <image src='/images/icon/icon_home.png' mode='aspectFill' class='back-home'></image>
      </view>

本文完~,喜歡就點個讚唄。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章