一、項目目錄結構
說明:
1、components目錄用於存放自定義組件,bar是一個自定義組件,封裝了小程序頂部自定義導航欄。
1>由於頂部導航欄大多頁面都需要,所以最好封裝成一個組件,直接引入,這也就引發了第二個需求。
2>有時,在一個項目中,有些頁面的導航欄可能不一樣,所以此時我們應該儘可能的考慮到需求,然後封裝,在頁面更改值來達到不同的導航欄需求。
2、pages下存放頁面。
3、小程序自定義組件中不能使用app.wxss中的樣式,所以組件中共用的樣式、iconfont圖標單獨放在一個wxss文件中,然後直接引入即可~
二、版本
此次會給出2個版本的自定義導航欄
1、微信小程序版本的 源碼下載:https://github.com/Syleapn/wx-custom-navigation
2、uni-app版本的 源碼下載:https://github.com/Syleapn/uni-app-custom-navigation-
其實兩者差不多,只是寫法上稍微有點區別,考慮到大多小夥伴初次對微信小程序熟悉,那本次就以微信小程序版本爲例剖析,uni-app直接貼出代碼或放到git上面下載!
三、分析
1、小程序自定義導航欄知識點補充
微信小程序導航欄:由狀態欄與標題欄組成
除了狀態欄與右上角膠囊外,其他區域都可由開發者控制,
狀態欄高度:由系統信息獲取:statusBarHeight
標題欄高度:ios:44px android:48px
得到狀態欄與標題欄的高度後我們可以自定義微信小程序導航欄,從而達到項目需求。
2、圖片展示
更多相關或微信小程序設計指南請點擊這裏:https://developers.weixin.qq.com/miniprogram/design/
四、實現過程分析
1、先進行自定義導航欄封裝(bar文件)
bar.wxml
<!-- 微信小程序導航欄:由狀態欄與標題欄組成
除了狀態欄與右上角膠囊外,其他區域都可由開發者控制,
狀態欄高度:由系統信息獲取:statusBarHeight
標題欄高度:ios:44px android:48px
得到狀態欄與標題欄的高度後我們可以自定義微信小程序導航欄,從而達到項目需求 -->
<!-- 說明:
1、第一種情況:爲了便於說明導航欄的組成,添加了一個標籤,“狀態欄”所在的這個標籤
在web前端開發中,通常情況下,當我們自定義頂部導航欄時,要進行fixed,這樣會脫離標準流,導致後面的正文一部分覆蓋在導航欄下面
,通常的做法是:
把正文距離頂部向下移動導航欄高度的距離。此處爲了不向父組件傳值,直接在子組件(自定義導航欄)中解決這個問題,採用另一種思路。
就是添加一個額外的標籤,結合css樣式達到相同的目的。這個額外的標籤可以包裹在整個導航欄外面(像第一種與第三種情況),
也可以與導航欄平級(第二種情況)
2、終極情況:換繁爲簡,後續可以採用第二或第三種方案去實現自定義導航欄!
-->
<!--第一種情況 -->
<!-- 額外標籤 -->
<view style="height: {{titleBarHeight}};padding-top:{{statusBarHeight}}">
<!--導航欄 -->
<view class="bar-view">
<!-- 狀態欄 -->
<view class="weight statuColumn" style="height: {{statusBarHeight}}">狀態欄</view>
<!-- 標題欄 -->
<view class="titleColumn" style="height:{{titleBarHeight}};background-color: {{nav.bg}}">
<text class="iconfont leftArrow titleColumn-back weight" style="border:{{nav.color}}" wx:if="{{nav.isdisPlayNavTitle}}" bindtap="back"></text>
<view class="titleColumn-title weight">{{nav.navTitle}}</view>
</view>
</view>
</view>
<!-- 第二種情況 -->
<!-- 導航欄 -->
<view class="header" style="height:{{titleBarHeight}};padding-top:{{statusBarHeight}};background-color:{{nav.bg}}">
<text class="iconfont leftArrow header-back weight" style="border:{{nav.color}}" wx-if="{{nav.isdisPlayNavTitle}}" bindtap="back"></text>
<view class="header-title weight">{{nav.navTitle}}</view>
</view>
<!-- 額外標籤 -->
<view style="height:{{titleBarHeight}};padding-top:{{statusBarHeight}}"></view>
<!-- 第三種情況 -->
<view style="height:{{titleBarHeight}};padding-top:{{statusBarHeight}}">
<view class="header" style="height:{{titleBarHeight}};padding-top:{{statusBarHeight}};background-color: {{nav.bg}}">
<text class="iconfont leftArrow header-back weight" style="border:{{nav.color}}" wx:if="{{nav.isdisPlayNavTitle}}" bindtap="back"></text>
<view class="header-title weight">{{nav.navTitle}}</view>
</view>
</view>
bar.js
Component({
properties:{
nav:{
type:Object
}
},
data:{
statusBarHeight: 0, //狀態欄初始化
titleBarHeight: 0, //標題欄初始化
},
ready: function () {
var that = this;
wx.getSystemInfo({
success: function (res) {
// model設備型號
// iOS
// 標題欄高度
if (res.model.indexOf('iPhone') !== -1) {
that.setData({
titleBarHeight: 44 + 'px'
})
} else {
// android
that.setData({
titleBarHeight: 48 + 'px'
})
}
// 狀態欄高度
that.setData({
statusBarHeight: res.statusBarHeight + 'px'
})
},
})
}
})
bar.wxss
@import '/iconfont/font.wxss';
/* ****************** 第一種情況樣式 ******************* */
.bar-view{
width:750rpx;
position: fixed;
top:0;
left:0;
z-index:100;
margin-bottom: 200px;
}
/* 狀態欄樣式 */
.statuColumn{
width:100%;
text-align: center;
background-color: green;
color:#fff;
}
/* 標題欄樣式 */
.titleColumn {
display: flex;
align-items: center;
width: 100%;
position: relative;
}
.titleColumn .titleColumn-title {
position: absolute;
left: 50%;
font-size: 38upx;
transform: translateX(-50%);
}
.titleColumn-back{
position: absolute;
left:15upx;
font-size:30upx;
padding: 10upx;
border-radius: 50%;
}
/* ************** 第二種與第三種情況樣式 ********************* */
.header {
display: flex;
align-items: center;
top: 0;
position: fixed;
width: 100%;
z-index: 100;
left:0;
}
.header .header-title {
position: absolute;
left: 50%;
font-size: 38upx;
transform: translateX(-50%);
}
.header-back{
position: absolute;
left:15upx;
font-size:30upx;
padding: 10upx;
border-radius: 50%;
}
2、引用文件
index.wxml
<bar nav="{{setNav}}"></bar>
<view class="" style="height:3000rpx;background-color:pink;">
正文
</view>
index.js
Page({
data:{
setNav: {
bg: 'yellow', //背景色
color: 'red', //字體顏色
isdisPlayNavTitle: true, //是否顯示返回按鈕,由於導航欄是共用的,把所有的東西封裝好,
// 然後有些頁面不需要的東西通過條件控制進行顯示與隱藏
navTitle: '標題欄' //導航標題
}
}
})
五、第二與第三種情況結果展示
六、說明
關於組件傳值可以看這裏:https://blog.csdn.net/Syleapn/article/details/97286960
此處不再說明~