uniapp微信小程序自定義導(dǎo)航欄的全過程
前言
相信很多小伙伴在使用uniapp進行多端開發(fā)的時候呢,在面對一些奇葩的業(yè)務(wù)需求的時候,uniapp給我們提供的默認導(dǎo)航欄已經(jīng)不能滿足我們的業(yè)務(wù)需求了,這個時候就需要我們自己自定義導(dǎo)航欄使用啦。
當然uniapp也給我們提供了很多的自定義導(dǎo)航欄的插件供大家使用,今天也給大家分享一個我自己寫的導(dǎo)航欄啦,希望大家多多指點
首先我們在自定義導(dǎo)航欄的時候,我們需要知道頭部的導(dǎo)航欄有哪幾部分組成,那么我們以微信小程序為例

可以看到在微信小程序中,我們的頭部導(dǎo)航欄其實受到右上角膠囊的限制比較大,這個時候我們自定義的導(dǎo)航欄,需要做到標題于膠囊水平對齊,那其實這個時候整個頭部其實主要又:狀態(tài)欄的高度+標題欄的高度組成。
狀態(tài)欄的高度我們可以通過uni.getSystemInfoSync().statusBarHeight來獲取。
那么標題欄的高度我們怎么獲取呢?
其實要想定義標題欄的高度,我們需要知道這個膠囊的位置,在小程序中我們可以使用wx.getMenuButtonBoundingClientRect()獲取關(guān)于膠囊的信息

獲取到的膠囊的top,left,right分別對應(yīng)膠囊的上邊界,左邊界,右邊界相對于屏幕左上角的起點的位置,所以我們是不是可以用(膠囊上邊界距離頂部的距離 - 狀態(tài)欄的高度)*2+膠囊的高度,就是標題欄的高度呢?然后再在標題欄里面添加一個文本區(qū)讓他的高度等于膠囊的高度,實現(xiàn)flex布局的上下居中是不是就搞定了呢?
以上呢其實針對小程序平臺的導(dǎo)航欄講解,那么既然使用uniapp,就會考慮到多端情況
那么其實我們使用uniapp獲取到的狀態(tài)欄在h5,小程序和app原生都是有效的,h5網(wǎng)頁中一般我們都是直接采用瀏覽器內(nèi)核給我們內(nèi)置的網(wǎng)頁導(dǎo)航欄,就是一個頭部,沒有過多的要求,而且瀏覽器不同,給我們提供的頭部導(dǎo)航也不一樣。
而對于app端,我們沒有了像微信小程序中那種讓人心煩的膠囊之后,我們只需要知道狀態(tài)欄的高度,然后加上自己業(yè)務(wù)需求的標題欄樣式和標題欄高度就行啦
所以我們在進行自定義導(dǎo)航欄封裝的時候就要對代碼進行條件編譯啦。那么我這里呢是把微信小程序做了單獨的處理,微信小程序之外的平臺看作是統(tǒng)一狀態(tài)
獻上源碼:
首先我們把獲取設(shè)備信息的代碼封裝到一個統(tǒng)一的js文件里面,這樣方便我們在組件中獲取也方便我們在頁面中獲取。

/**
* 此js文件管理關(guān)于當前設(shè)備的機型系統(tǒng)信息
*/
const systemInfo = function() {
/****************** 所有平臺共有的系統(tǒng)信息 ********************/
// 設(shè)備系統(tǒng)信息
let systemInfomations = uni.getSystemInfoSync()
// 機型適配比例系數(shù)
let scaleFactor = 750 / systemInfomations.windowWidth
// 當前機型-屏幕高度
let windowHeight = systemInfomations.windowHeight * scaleFactor //rpx
// 當前機型-屏幕寬度
let windowWidth = systemInfomations.windowWidth * scaleFactor //rpx
// 狀態(tài)欄高度
let statusBarHeight = (systemInfomations.statusBarHeight) * scaleFactor //rpx
// 導(dǎo)航欄高度 注意:此導(dǎo)航欄高度只針對微信小程序有效 其他平臺如自定義導(dǎo)航欄請使用:狀態(tài)欄高度+自定義文本高度
let navHeight = 0 //rpx
// console.log(windowHeight,'哈哈哈哈哈');
/****************** 微信小程序頭部膠囊信息 ********************/
// #ifdef MP-WEIXIN
const menuButtonInfo = wx.getMenuButtonBoundingClientRect()
// 膠囊高度
let menuButtonHeight = menuButtonInfo.height * scaleFactor //rpx
// 膠囊寬度
let menuButtonWidth = menuButtonInfo.width * scaleFactor //rpx
// 膠囊上邊界的坐標
let menuButtonTop = menuButtonInfo.top * scaleFactor //rpx
// 膠囊右邊界的坐標
let menuButtonRight = menuButtonInfo.right * scaleFactor //rpx
// 膠囊下邊界的坐標
let menuButtonBottom = menuButtonInfo.bottom * scaleFactor //rpx
// 膠囊左邊界的坐標
let menuButtonLeft = menuButtonInfo.left * scaleFactor //rpx
// 微信小程序中導(dǎo)航欄高度 = 膠囊高度 + (頂部距離 - 狀態(tài)欄高度) * 2
navHeight = menuButtonHeight + (menuButtonTop - statusBarHeight) * 2
// #endif
// #ifdef MP-WEIXIN
return {
scaleFactor,
windowHeight,
windowWidth,
statusBarHeight,
menuButtonHeight,
menuButtonWidth,
menuButtonTop,
menuButtonRight,
menuButtonBottom,
menuButtonLeft,
navHeight
}
// #endif
// #ifndef MP-WEIXIN
return {
scaleFactor,
windowHeight,
windowWidth,
statusBarHeight
}
// #endif
}
export {
systemInfo
}然后我們定義一個導(dǎo)航欄組件

/*
* 注意:
* 1、在傳入寬度或者高度時,如果是Number數(shù)據(jù),傳入的值為px大小,無需帶單位,組件自動計算
* 2、在使用此導(dǎo)航欄時,建議傳入UI規(guī)定的導(dǎo)航欄高度,此高度只針對除微信小程序的其他平臺有效,微信小程序的導(dǎo)航欄高度,組件自計算
*/
<template>
<view>
<!-- 微信小程序頭部導(dǎo)航欄 -->
<!-- #ifdef MP-WEIXIN -->
<view class="wx-head-mod" :style="{height:navHeight+'rpx',backgroundColor:navBackgroundColor}">
<view class="wx-head-mod-nav" :style="{height:navigationBarHeight+'rpx',top:statusBarHeight+'rpx'}">
<view class="wx-head-mod-nav-content"
:style="{height:customHeight+'rpx',justifyContent:textAlign === 'center'?'center':'left'}">
<!-- 文本區(qū) -->
<view class="wx-head-mod-nav-content-mian"
:style="{width:navTextWidth,lineHeight:customHeight + 'rpx',paddingLeft:textPaddingLeft*scaleFactor+'rpx',fontSize:fontSize*scaleFactor+'rpx',fontWeight:fontWeight,color:titleColor}">
{{textContent}}
</view>
<!-- 返回按鈕 -->
<view class="wx-head-mod-nav-content-back" :style="{display:isBackShow?'flex':'none'}"
@click="backEvent">
<view class="wx-head-mod-nav-content-back-img"
:style="{width:backImageWidth*scaleFactor+'rpx',height:backImageHeight*scaleFactor+'rpx'}">
<image :src="backImageUrl" mode="" style="width: 100%;height: 100%;"></image>
</view>
</view>
</view>
</view>
</view>
<!-- #endif -->
<!-- 除微信小程序之外的其他設(shè)備 -->
<!-- #ifndef MP-WEIXIN -->
<view class="other-head-mod"
:style="{height:navHeightValue*scaleFactor+statusBarHeight+'rpx',backgroundColor:navBackgroundColor}">
<view class="other-head-mod-mian"
:style="{height:navHeightValue*scaleFactor+'rpx',justifyContent:textAlign === 'center'?'center':'left'}">
<!-- 返回按鈕 -->
<view class="other-head-mod-mian-back" v-show="isBackShow" @click="backEvent">
<view class="other-head-mod-mian-back-img"
:style="{width:backImageWidth*scaleFactor+'rpx',height:backImageHeight*scaleFactor+'rpx'}">
<image :src="backImageUrl" mode="" style="width: 100%;height: 100%;"></image>
</view>
</view>
<!-- 標題 -->
<view class="other-head-mod-mian-title" :style="{width:windowWidth - 184+'rpx',lineHeight:navHeightValue*scaleFactor+'rpx',
paddingLeft:textPaddingLeft*scaleFactor+'rpx',fontSize:fontSize*scaleFactor+'rpx',
fontWeight:fontWeight,color:titleColor}">
{{textContent}}
</view>
</view>
</view>
<!-- #endif -->
</view>
</template>
<script>
const app = getApp()
import {systemInfo} from '@/common/system-info.js'
export default {
name: "HeadView",
props: {
// 文本區(qū)域位置 left:左 center:中
textAlign: {
type: String,
default: 'center'
},
// 文本區(qū)內(nèi)容
textContent: {
type: String,
default: '哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈就啊哈哈好借好還'
},
// 文本區(qū)離左邊的距離
textPaddingLeft: {
type: Number,
default: 16
},
// 是否需要返回按鈕
isBackShow: {
type: Boolean,
default: true
},
// 文本區(qū)字體大小
fontSize: {
type: Number,
default: 20 //px
},
// 文本區(qū)字體粗細
fontWeight: {
type: Number,
default: 700
},
// 文本區(qū)返回按鈕圖片寬
backImageWidth: {
type: Number,
default: 12 //px
},
// 文本區(qū)返回按鈕圖片高
backImageHeight: {
type: Number,
default: 24 //px
},
// 返回按鈕圖標路徑
backImageUrl: {
type: String,
default: '/static/backImage.svg'
},
// 導(dǎo)航欄整體背景顏色
navBackgroundColor: {
type: String,
default: '#2476F9'
},
// 標題字體顏色
titleColor: {
type: String,
default: '#ffffff',
},
/******** h5端,app端需要傳入自定義導(dǎo)航欄高度 *******/
navHeightValue: {
type: Number,
default: 44 //px
}
},
computed: {
// 文本區(qū)寬度
navTextWidth() {
if (this.textAlign === 'center') {
return (this.windowWidth - (this.windowWidth - this.menubarLeft) * 2) + 'rpx'
} else {
return this.menubarLeft + 'rpx'
}
},
// 文本區(qū)paddingLeft
textPaddingleft() {
if (this.textAlign === 'center') {
return '0'
} else {
return this.textPaddingLeft + 'rpx'
}
}
},
data() {
return {
statusBarHeight: app.globalData.statusBarHeight, //狀態(tài)欄高度
navHeight: app.globalData.navHeight, //頭部導(dǎo)航欄總體高度
navigationBarHeight: app.globalData.navigationBarHeight, //導(dǎo)航欄高度
customHeight: app.globalData.customHeight, //膠囊高度
scaleFactor: app.globalData.scaleFactor, //比例系數(shù)
menubarLeft: app.globalData.menubarLeft, //膠囊定位的左邊left
windowWidth: app.globalData.windowWidth * app.globalData.scaleFactor
};
},
methods: {
backEvent() {
uni.navigateBack({
delta: 1
})
}
},
created() {
/* 獲取設(shè)備信息 */
const SystemInfomations = systemInfo()
/* 通用平臺 */
this.statusBarHeight = SystemInfomations.statusBarHeight //狀態(tài)欄高度
this.scaleFactor = SystemInfomations.scaleFactor //比例系數(shù)
this.windowWidth = SystemInfomations.windowWidth //當前設(shè)備的屏幕寬度
/* 微信小程序平臺 */
// #ifdef MP-WEIXIN
this.navHeight = SystemInfomations.navHeight + SystemInfomations.statusBarHeight //頭部導(dǎo)航欄總高度
this.navigationBarHeight = SystemInfomations.navHeight //頭部導(dǎo)航欄高度
this.customHeight = SystemInfomations.menuButtonHeight //膠囊高度
this.menubarLeft = SystemInfomations.menuButtonLeft //膠囊左邊界距離左上角的距離
// #endif
}
}
</script>
<style>
/* #ifdef MP-WEIXIN */
.wx-head-mod {
box-sizing: border-box;
width: 100%;
position: fixed;
top: 0;
left: 0;
}
.wx-head-mod-nav {
box-sizing: border-box;
width: 100%;
position: absolute;
left: 0;
display: flex;
justify-content: center;
align-items: center;
}
.wx-head-mod-nav-content {
box-sizing: border-box;
width: 100%;
display: flex;
justify-content: left;
align-items: center;
position: relative;
}
/* 文本區(qū) */
.wx-head-mod-nav-content-mian {
box-sizing: border-box;
height: 100%;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
}
/* 返回按鈕 */
.wx-head-mod-nav-content-back {
box-sizing: border-box;
width: 60rpx;
height: 100%;
/* background-color: aqua; */
position: absolute;
top: 0;
left: 32rpx;
display: flex;
align-items: center;
justify-content: left;
}
.wx-head-mod-nav-content-back-img {
box-sizing: border-box;
}
/* #endif */
/* #ifndef MP-WEIXIN */
.other-head-mod {
box-sizing: border-box;
width: 100%;
position: fixed;
top: 0;
left: 0;
}
.other-head-mod-mian {
box-sizing: border-box;
width: 100%;
display: flex;
align-items: center;
justify-content: left;
position: absolute;
left: 0;
bottom: 0;
}
/* 返回按鈕 */
.other-head-mod-mian-back {
box-sizing: border-box;
height: 100%;
width: 60rpx;
position: absolute;
left: 32rpx;
top: 0;
display: flex;
align-items: center;
}
/* 標題 */
.other-head-mod-mian-title {
box-sizing: border-box;
height: 100%;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
}
/* #endif */
</style>組件使用:
引入組件:
import HeadNav from '@/components/HeadNav.vue'
組冊組件:
components:{
HeadNav
},<template> <view class="content"> <head-nav></head-nav> <view class="content-main"></view> </view> </template>
效果圖:
微信小程序:

h5:

app:

在項目里面沒有針對h5時候需要導(dǎo)航欄做特別的限制,如果實際開發(fā)中在h5端不需要此導(dǎo)航欄,請在模版上面針對h5頁面加入條件編譯即可。
總結(jié)
到此這篇關(guān)于uniapp微信小程序自定義導(dǎo)航欄的文章就介紹到這了,更多相關(guān)uniapp自定義導(dǎo)航欄內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- 微信小程序自定義頂部導(dǎo)航欄并適配不同機型實例詳解
- 微信小程序動態(tài)設(shè)置導(dǎo)航欄標題的實現(xiàn)步驟
- 小程序自定義tabbar導(dǎo)航欄及動態(tài)控制tabbar功能實現(xiàn)方法(uniapp)
- 微信小程序使用uni-app實現(xiàn)首頁搜索框?qū)Ш綑诠δ茉斀?/a>
- uniapp小程序配置tabbar底部導(dǎo)航欄實戰(zhàn)指南
- 微信小程序自定義漸變的tabbar導(dǎo)航欄功能
- uniapp開發(fā)微信小程序自定義頂部導(dǎo)航欄功能實例
- 微信小程序?qū)崿F(xiàn)側(cè)邊導(dǎo)航欄
- 微信小程序?qū)崿F(xiàn)自定義導(dǎo)航欄
- 微信小程序自定義導(dǎo)航欄功能的實現(xiàn)
相關(guān)文章
JavaScript設(shè)置body高度為瀏覽器高度的方法
這篇文章主要介紹了JavaScript設(shè)置body高度為瀏覽器高度的方法,實例分析了body高度的設(shè)置技巧,具有一定參考借鑒價值,需要的朋友可以參考下2015-02-02
MATLAB中fillmissing函數(shù)用法小結(jié)
這篇文章主要介紹了MATLAB中fillmissing函數(shù)用法,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-09-09
js簡單實現(xiàn)HTML標簽Select聯(lián)動帶跳轉(zhuǎn)
Select聯(lián)動帶跳轉(zhuǎn)的效果想必大家并不陌生吧,下面有個不錯的示例,感興趣的朋友可以參考下2013-10-10
JS調(diào)用頁面表格導(dǎo)出excel示例代碼
這篇文章主要介紹了JS調(diào)用頁面表格導(dǎo)出excel的具體實現(xiàn),需要的朋友可以參考下2014-03-03
Echarts讀取動態(tài)數(shù)據(jù)完整代碼
這篇文章主要給大家介紹了關(guān)于Echarts讀取動態(tài)數(shù)據(jù)的相關(guān)資料,使用Echarts畫圖時,數(shù)據(jù)一般不是靜態(tài)寫死的,而是通過后端接口動態(tài)獲取的,需要的朋友可以參考下2023-10-10

