微信小程序自定義導航欄組件

相信不少小夥伴在開發微信小程序的時候都會有自定義頂部導航欄的需求,不夠要說明的是小程序右上角的膠囊是不能自定義的哦,除了膠囊其餘地方都是能夠根據本身的項目而定了,在一次小程序開發中就須要對頂部進行自定義在此記錄一下本身封裝這個組件的過程。json

組件編寫

既然今天須要把導航欄封裝爲組件那麼就須要如下幾個步驟:小程序

組件結構搭建

首先搭建一個以下圖的結構:微信小程序

而後在index中引入剛剛建立好的組件:

記得在json文件中添加引用路徑如圖一,此時就會看到首頁效果以下:

組件基礎代碼編寫

此時咱們就須要根據官方文檔查看得知若是要定製必須在配置文件中修改默認的配置文件,其實這裏能夠針對某個頁面page進行設置,以index爲例在index.json文件中配置以下代碼便可看到以下效果:api

這個時候咱們就能夠開始寫本身想要的樣子了,首先寫一個簡單的就只有一個返回按鈕,當開始寫的時候就會發現一個很大的問題,這塊高度多少?最上面的狀態欄高度又是多少?貌似被這兩個問題難住了,這個時候再去看看官方的api文檔你會發現能夠獲取系統當前更多參數裏面就有狀態欄高度,如圖:

其實想一想咱們只知道狀態欄高度,除了狀態欄的高度其他高度呢?又是一個問題。從微信小程序的官方設計文檔中能夠知道這部分高度貌似同樣高,如圖:

貌似這塊多高均可以,畢竟還能夠向下延伸,通過屢次測試(可能不許確)在蘋果好安卓仍是會有差異的,因此本身弄了一個適配一部分的(貌似舊手機不支持沉沉侵式)。可能廢話太多,直接上代碼吧

結構
<view class='topbar'>
  <view class='status' style="height:{{statusHeight}}px"></view>
  <view class='navbar' style="height:{{navHeight}}px">
    <view class='navbar_back' bindtap='backClick'>
      <image src='../images/black_back.png'></image>
    </view>
    <view class='navbar_title' style="height:{{navHeight}}px">
      <view>標題</view>
    </view>
  </view>
</view>
複製代碼

這裏的主要思路就是用fixed定位,後面會有內容頂到底部的佈局,因此所有用定位會方便些,總體就兩個部分一個是狀態欄一個就是標題和按鈕的部分了。bash

樣式
.topbar {
  position: fixed;
  left: 0;
  top: 0;
  width: 100%;
  z-index: 9999;
}
.status {
  width: 100%;
}
.navbar {
  width: 100%;
  display: flex;
  justify-content: flex-start;
  align-items: center;
  position: relative;
}

.navbar_back {
  padding: 0 32rpx;
  display: flex;
  justify-content: flex-start;
  align-items: center;
  height: 100%;
}

.navbar_back image {
  width: 21rpx;
  height: 34rpx;
}

.navbar_title {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  text-align: center;
  display: flex;
  justify-content: center;
  align-items: center;
  z-index: -1;
}
.navbar_title view {
  width: 40%;
  word-break: break-all;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 38rpx;
}
複製代碼

樣式中沒有太多的東西,惟一須要說的就是大部分模塊都是定位作的,惟一沒考慮好的就是標題太長很差處理,這裏用了簡單粗暴的方法給設定一個寬度。微信

邏輯處理
Component({
  properties: {
    /**
     * 自定義返回事件處理
     * customBackReturn="{{true}}" bind:customBackReturn="customBackReturn"
     */
    customBackReturn: {
      type: Boolean,
      value: false
    }
  },
  data: {

  },
  methods: {
    backClick() {
      if (this.data.customBackReturn) {
        this.triggerEvent("customBackReturn")
      } else {
        if (getCurrentPages().length == 1) {
          wx.switchTab({
            url: '/pages/index/index',
          })
        } else {
          wx.navigateBack({
            delta: 1
          })
        }
      }
    }
  },
  attached() {
    var self = this;
    wx.getSystemInfo({
      success(res) {
        var isIos = res.system.indexOf('iOS') > -1;
        self.setData({
          statusHeight: res.statusBarHeight,
          navHeight: isIos ? 44 : 48
        })
      }
    })
  }
})
複製代碼

邏輯中主要在兩個地方一個是獲取系統信息時對於導航高度的判斷,另一個是返回上一頁的邏輯,默認就是打開首頁(注意用的api),若是有自定義事件就用自定義事件customBackReturnapp

效果

目前效果就和沒有自定義以前差很少就是一個普通的返回按鈕和標題文字,以下圖:佈局

那麼這樣一個簡單的自定義導航欄就ok了,可是若是是這樣那我還自定義幹嗎用小程序自帶的不是更好,因此咱們要繼續改進,給加一個返回主頁的按鈕。

帶返回按鈕的導航

小程序中特別是分享出去的頁面,若是沒有一個返回主頁的按鈕,用戶更本不知道怎麼回到小程序的主頁,因此給用戶帶來了很大的不便,所以這樣的需求就必需要有了,若是實現呢?其實很簡單,畢竟已經出來一個了,須要的就是加一個上去就好了。測試

結構
<view class='topbar'>
  <view class='status' style="height:{{statusHeight}}px"></view>
  <view class='navbar' style="height:{{navHeight}}px">
    <view class='navbar_home'>
      <image src='../images/black_back.png' bindtap='backClick'></image>
      <image src='../images/home_black.png' bindtap='homeClick'></image>
    </view>
    <!-- <view class='navbar_back' bindtap='backClick'>
      <image src='../images/black_back.png'></image>
    </view> -->
    <view class='navbar_title' style="height:{{navHeight}}px">
      <view>標題</view>
    </view>
  </view>
</view>
複製代碼

你們注意到我把以前的代碼註釋了而不是直接在前面的代碼上修改,其實這裏留着是爲了後面能夠自定義想要那種導航形式。flex

樣式
.navbar_home {
  margin-left: 32rpx;
  display: flex;
  justify-content: flex-start;
  align-items: center;
  border-radius: 33rpx;
  border: 1px solid rgba(0, 0, 0, 0.1);
  background: rgba(0,0,0,0.2);
  box-sizing: border-box;
  padding: 10rpx 0;
}

.navbar_home image:first-child {
  width: 21rpx;
  height: 34rpx;
  padding: 0 32rpx;
  border-right: 1px solid rgba(255,255,255,0.2);
}

.navbar_home image:last-child {
  width: 37rpx;
  height: 35rpx;
  padding: 0 32rpx;
}
複製代碼

一樣的樣式也只是在以前的基礎上增長了上面這些樣式。

邏輯
homeClick() {
      wx.switchTab({
        url: '/pages/index/index',
      })
    }
複製代碼

邏輯也只是在methods中添加一個返回主頁的事件而已,這裏須要你們根據本身的項目狀況而定。

效果

樣式你們能夠根據本身項目而定。

到這兩部分的功能都完成了,可是若是如今咱們在首頁中添加一些內容你就會發現問題了,以下:

咱們的內容也跑到上面了,不過這麼一想內容頂到頂部不就是這種效果嗎,因此解決了這個問題,可如今的問題是不想要這種怎麼辦呢?想一想這個應該很好辦啊,我在這一部分給加一個等高的塊不定位不就能夠了,因此如今就來實現它,代碼以下:

<view style="height:{{statusHeight+navHeight}}px" hidden='{{false}}'></view>
<view class='topbar'>
  <view class='status' style="height:{{statusHeight}}px"></view>
  <view class='navbar' style="height:{{navHeight}}px">
    <view class='navbar_home'>
      <image src='../images/black_back.png' bindtap='backClick'></image>
      <image src='../images/home_black.png' bindtap='homeClick'></image>
    </view>
    <!-- <view class='navbar_back' bindtap='backClick'>
      <image src='../images/black_back.png'></image>
    </view> -->
    <view class='navbar_title' style="height:{{navHeight}}px">
      <view>標題</view>
    </view>
  </view>
</view>
複製代碼

效果以下:

當咱們把false改成true是就能夠獲得內容頂到頂部的效果了,因此這樣就實現了兩種效果,既然咱們這裏是封裝爲組件,那麼咱們不可能就這樣寫的,須要進行一些封裝,而後給其餘頁面配置而後使用,因此須要改造。

封裝導航欄使其可定製化

爲了能使使用更加方便,須要對上面的導航欄進行進一步封裝以適應不一樣需求。

結構改造

首先須要改造的就是結構,讓更多的選項可以進行配置,結構改造以下:

<view style="height:{{statusHeight+navHeight}}px" hidden='{{header.hiddenBlock}}'></view>
<view class='topbar' style="background:{{header.headerbg}}">
  <view class='status' style="height:{{statusHeight}}px"></view>
  <view class='navbar' style="height:{{navHeight}}px">
    <block wx:if="{{header.slot}}">
      <slot></slot>
    </block>
    <block wx:else>
      <view class='navbar_home' wx:if="{{header.homeCapsule}}" style="background:{{header.capsulebg}};border:{{header.capsuleborder}}">
        <image src='../images/black_back.png' bindtap='backClick' style="border-right:{{header.capsulesep}}"></image>
        <image src='../images/home_black.png' bindtap='homeClick'></image>
      </view>
      <view class='navbar_back' bindtap='backClick' wx:else>
        <image src='../images/black_back.png'></image>
      </view>
      <view class='navbar_title' style="height:{{navHeight}}px">
        <view style="color:{{header.fontColor}};font-size:{{header.fontSize}}">{{header.title}}</view>
      </view>
    </block>
  </view>
</view>
複製代碼

上面全部的參數都是能夠配置的,這就大大的給了開發者定製不一樣風格了,若是仍是有不符合的建議你直接修改上面的代碼或者本身封裝一個更好。

邏輯改造
Component({
  properties: {
    header: {
      type: Object,
      value: {
        homeCapsule: false,
        headerbg: "#fff",
        title: "",
        fontColor: "#000",
        fontSize: '16',
        hiddenBlock: false,
        capsulebg: 'rgba(0,0,0,0.2)',
        capsuleborder: '1px solid rgba(0, 0, 0, 0.1)',
        capsulesep: '1px solid rgba(255,255,255,0.2)',
        slot: false
      }
    },
    /**
     * 自定義返回事件處理
     * customBackReturn="{{true}}" bind:customBackReturn="customBackReturn"
     */
    customBackReturn: {
      type: Boolean,
      value: false
    }
  },
  methods: {
    backClick() {
      if (this.data.customBackReturn) {
        this.triggerEvent("customBackReturn")
      } else {
        if (getCurrentPages().length == 1) {
          wx.switchTab({
            url: '/pages/index/index',
          })
        } else {
          wx.navigateBack({
            delta: 1
          })
        }
      }
    },
    homeClick() {
      wx.switchTab({
        url: '/pages/index/index',
      })
    }
  },
  attached() {
    var self = this;
    wx.getSystemInfo({
      success(res) {
        var isIos = res.system.indexOf('iOS') > -1;
        self.setData({
          statusHeight: res.statusBarHeight,
          navHeight: isIos ? 44 : 48
        })
      }
    })
  }
})
複製代碼

結構的改造其實就是添加一些可以傳入的值來定製化。

到這裏基本上這個組件就封裝好了,接下來就是使用這個組件了。

常規帶有一個返回按鈕的案例

這種方式的應用很簡單直接配置一些參數便可。

先引入組件以下:
{
  "navigationStyle":"custom",
  "usingComponents": {
    "header":"../../components/navbar/navbar"
  }
}
複製代碼

須要配置導航欄自定義,否則就沒有效果,根據本身的路徑引入便可,若是全部頁面都須要用到,建議直接在app.json中配置,這樣就不用每一個頁面去配置了。

wxml中使用組件標籤
<header header='{{header}}'></header>
<view>內容區域哦</view>
複製代碼

在須要用到的頁面使用header標籤便可

js文件中配置參數
Page({
  data: {
    header:{
      homeCapsule: false,
      title: '標題',
      fontColor: "#000",
      fontSize: '36rpx',
      headerbg: '#f40',
      hiddenBlock: false,
      slot: false
    }
  },
  onLoad: function() {}
});
複製代碼

這裏有三個參數是必需要配置的:homeCapsule,hiddenBlock,slot三個參數分別表明的含義是是否顯示帶有home按鈕的,是否隱藏整個頂部(後面會介紹),是否須要自定義結構

效果

那麼這個最基本的就實現了。

內容置頂的實例

有時候須要將內容置頂,看起來會比較好看,因此就須要對hiddenBlock進行配置了,看代碼:

<header header='{{header}}'></header>
<image src='../../images/timg.jpg' style="width:100%" mode="aspectFill"></image>
<view>內容區域哦</view>
複製代碼

重要的是如何配置,以下:

Page({
  data: {
    header:{
      homeCapsule: false,
      title: '',
      headerbg: 'transparent',
      hiddenBlock: true,
      slot: false
    }
  },
  onLoad: function() {}
});
複製代碼

效果以下:

帶有home按鈕的導航

分享頁須要帶有返回首頁的按鈕,如何配置呢?有了這個組件就很容易配置了,配置以下:

Page({
  data: {
    header:{
      homeCapsule: true,
      title: '測試標題',
      headerbg: '#f40',
      hiddenBlock: false,
      slot: false
    }
  },
  onLoad: function() {}
});
複製代碼

效果以下:

徹底自定義

若是以上都不能知足需求,那麼只有本身寫了,簡單實例以下:

<header header='{{header}}'>
  <view>測試的標題哦</view>
</header>
<image src='../../images/timg.jpg' style="width:100%" mode="aspectFill"></image>
<view>內容區域哦</view>
複製代碼

配置以下:

Page({
  data: {
    header:{
      headerbg: 'transparent',
      hiddenBlock: false,
      slot: true
    }
  },
  onLoad: function() {}
});
複製代碼

效果以下:

固然啦,這裏只是簡單的舉個栗子而已,具體靠你們本身去實現了。 到此這組件大部分的封裝就完成了。謝謝你們哦!
相關文章
相關標籤/搜索