大家好,欢迎来到IT知识分享网。
1. 前言
小程序开发中,有时我们不需要自带的导航栏,那就需要自己写一个这样的导航栏。
2. 效果展示
3.文件目录结构
├── root │ ├── components │ │ └── navbar │ │ ├── index.js │ │ ├── index.wxml │ │ ├── index.json │ │ ├── index.wxss │ ├──pages │ │ ├── index.js │ │ ├── index.wxml │ │ ├── index.json │ │ ├── index.wxss └──── app.js
4.如何使用
pages/index
<navbar navbar-data="{
{navbarData}}"></navbar> Page({
data: {
navbarData: {
showCapsule: 1, //是否显示头部左上角小房子 1显示 0 不显示 showBack: 1, //是否显示返回 1显示 0不显示 // showColor: 0, //navbar背景颜色 1展示 0不展示 // navigationBarColor: 'yellow', bgTransparent: true, // 时候否透明 iconColor: 'black', titleColor: 'black', title: '首页' }, }, })
5. 实现代码
// app.js App({
onLaunch() {
const {
statusBarHeight, titleBarHeight } = getStatusBarHeight() console.log(statusBarHeight, titleBarHeight) this.globalData.statusBarHeight = statusBarHeight; this.globalData.titleBarHeight = titleBarHeight; }, globalData: {
statusBarHeight: "", titleBarHeight: "" } }) function getStatusBarHeight() {
let res = wx.getSystemInfoSync() let customTitleBarHeight; try {
const menuInfo = wx.getMenuButtonBoundingClientRect(); if (equalVersion(res.version, "7.0.3")) {
customTitleBarHeight = menuInfo.height + (menuInfo.top - res.statusBarHeight) * 2; } else {
customTitleBarHeight = menuInfo.height + menuInfo.top * 2; } } catch (e) {
customTitleBarHeight = 48; } if (res.model.indexOf("iPhone") !== -1) {
customTitleBarHeight = 44; } return {
statusBarHeight: res.statusBarHeight, titleBarHeight: customTitleBarHeight, } }; function equalVersion(curV, reqV) {
let arr1 = curV.split("."); let arr2 = reqV.split("."); let maxL = Math.max(arr1.length, arr2.length); let pos = 0; let diff = 0; while (pos < maxL) {
diff = parseInt(arr1[pos]) - parseInt(arr2[pos]); console.log(diff, parseInt(arr1[pos]), parseInt(arr2[pos])); if (diff != 0) {
break; } pos++; } if (diff > 0 || diff == 0) {
//新版本、稳定版 return 1; } else {
// 旧版本 return 0; } }
/ * 自定义头部 */ const app = getApp() // 版本号比较函数 function compareVersion(v1, v2) {
v1 = v1.split('.') v2 = v2.split('.') const len = Math.max(v1.length, v2.length) while (v1.length < len) {
v1.push('0') } while (v2.length < len) {
v2.push('0') } for (let i = 0; i < len; i++) {
const num1 = parseInt(v1[i]) const num2 = parseInt(v2[i]) if (num1 > num2) {
return 1 } else if (num1 < num2) {
return -1 } } return 0 } Component({
properties: {
navbarData: {
//navbarData 由父页面传递的数据,变量名字自命名 type: Object, value: {
}, observer: function (newVal, oldVal, changedPath) {
if (newVal == null && typeof (oldVal) == 'object') {
try {
var _o = {
}; var defaultData = {
statusBarHeight: '', titleBarHeight: '', navbarData: {
showCapsule: 1, //是否显示左上角小房子 1显示 0 不显示 showBack: 1, //是否显示返回 1显示 0不显示 showColor: 1, //navbar背景颜色 1蓝色 0白色 navigationBarColor: '#ffffff', bgTransparent: false, // true 背景为透明 false 不透明(下面两个属性也不生效) iconColor: 'black', // white 左侧icon颜色 titleColor: '#000000' // 可以指定title具体色值 } } _o['navibarData'] = defaultData['navbarData'] this.setData(_o); } catch (e) {
} } else {
// var data = this.data; var data = {
}; var path = 'navibarData'; Object.keys(newVal).forEach(key => {
data[`${
path}.${
key}`] = newVal[key]; }) this.setData(data); } } } }, data: {
statusBarHeight: '', titleBarHeight: '', showNavbar: '', menuButtonInfo: {
}, navibarData: {
showCapsule: 0, //是否显示左上角小房子 showBack: 1, //是否显示返回 showColor: 1, //navbar背景颜色, navigationBarColor: '#ffffff', bgTransparent: false, // true 背景为透明 false 不透明(下面两个属性也不生效) iconColor: 'black', // white 左侧icon颜色 titleColor: '#000000' // 可以指定title具体色值 } }, attached: function () {
if (wx.getSystemInfoSync().platform.toLowerCase().indexOf('devtools') != -1) {
this.setData({
showNavbar: true }); } else {
// 获取版本号 const version = wx.getSystemInfoSync().version if (compareVersion(version, '7.0.0') >= 0) {
// 版本号大于7.0.0时,显示自定义头部 this.setData({
showNavbar: true }) } else {
// // 版本号低于7.0.0时,隐藏自定义头部 this.setData({
showNavbar: false }) } } this.setData({
statusBarHeight: app.globalData.statusBarHeight, titleBarHeight: app.globalData.titleBarHeight }); //获取右上角胶囊的大小,为显示自定义icon做准备 this.setData({
menuButtonInfo: wx.getMenuButtonBoundingClientRect() }); }, ready() {
try {
const currentPages = getCurrentPages() const _o1 = {
} //无论如何返回按钮出现的规则不变 if (currentPages.length > 1) {
_o1.showBack = true; } else {
_o1.showBack = false; } this.setData({
navibarData: {
...this.data.navibarData, ..._o1 } }) } catch (e) {
} }, methods: {
//返回到首页 _backhome(e) {
wx.switchTab({
url: '/pages/home/homepage', }); }, _backlast(e) {
wx.navigateBack(); }, }, })
component/navbar.wxml
<view style="padding-top:{
{
navibarData.bgTransparent ? 0 : (statusBarHeight+titleBarHeight)}}px" wx:if='{
{showNavbar}}'> <view wx:if='{
{navibarData.bgTransparent}}' class="nav-wrap b-nav-wrap transparent-bg"> <template is="titleBarContent" data="{
{statusBarHeight,titleBarHeight,navibarData,menuButtonInfo}}"/> </view> <block wx:else> <view wx:if='{
{navibarData.showColor}}' class="nav-wrap" style='background-color:{
{
navibarData && navibarData.navigationBarColor}};'> <template is="titleBarContent" data="{
{statusBarHeight,titleBarHeight,navibarData,menuButtonInfo}}"/> </view> <view wx:else class="nav-wrap b-nav-wrap"> <template is="titleBarContent" data="{
{statusBarHeight,titleBarHeight,navibarData,menuButtonInfo}}"/> </view> </block> </view> <template name="titleBarContent"> <view class="status-bar" style="height:{
{
statusBarHeight}}px"></view> <view class="title-bar" style="height:{
{
titleBarHeight}}px"> <view class="title-bar-group {
{navibarData.showBack ^ navibarData.showCapsule ? 'only-group-icon' : navibarData.showBack && navibarData.showCapsule ? '' :'no-group-icon'}}"> <view class="title-bar-icon" bindtap='_backlast' wx:if='{
{navibarData.showBack}}'> <image wx:if="{
{navibarData.bgTransparent&&navibarData.iconColor == 'white'}}" src='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFAAAABQCAMAAAC5zwKfAAAApVBMVEUAAAD///+4/eNVAAAANnRSTlMACPH9+vbrsCsF5LwTDALcPTYhAd/Ik4J4ZFRMRkIyG9LNt6SZjGAvFg/Z1cKnoIdyaFomm2zHx4MpAAABcElEQVRYw+2YaXKCQBhEhwFRcEXBfd8xxpiYzP2PltR0pbzA+5FU8Q7w/tD012AqKir+B8F8ifp6qXM70DeJ3A8NStcZOs8J8rWa8m0HjK/Rle81YHwz63Xh2DCMQ++zMyh9O+fpQg94tZGv2WJ8WSrfMGF8x5rXRe9Qmg/OE/cYX7mVb91nfI+LfPU245tb+UbQ23ZXmmtTKM0350mhSj0X8hVnxrdM5btB5fKhNId3KM1vzmPnjK9dl+/yYHz9F/m2JeNbxPIdOtDbESnNR8NQKi5xht1y79usDMXBd31gMPa+rTqc8MidIxHk3MEUmeVOumjk3OgQrSs3i0Syd3Qav6LnMUYbIpoYQXWYBg3Zsso4ewdyZRy8VFaHHlyGoaYIwaogx5LWNTrntP/pjM/scxKz31D7xMBfedczVj9DGfMT+qWsMUvRi7m5Lfrr34zT9VNgD3swknFhMKY1/XPgWHad+zQkySIzFRUVf41vKdVQ6T8ZiacAAAAASUVORK5CYII=' mode='aspectFit' class='back-home-return'></image> <image wx:else src='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFAAAABQCAMAAAC5zwKfAAAAkFBMVEUAAAAzMzMzMzM1NTU6Ojo/Pz8zMzMzMzNEREQzMzMzMzM0NDRnZ2czMzMzMzMzMzMzMzM0NDQ0NDQ0NDQ2NjY3Nzf///8zMzMzMzMzMzMzMzMzMzMzMzM0NDQ0NDQzMzM0NDQ1NTU9PT0zMzMzMzMzMzMzMzM0NDQzMzM3Nzc3Nzc0NDQzMzM0NDQ2NjYzMzP3PMnqAAAAL3RSTlMA+vErDwj2sATs3TYC5uHQuU09MSETAdfJvaWak4J4ZEZCC8OgjGlgVRwYh3JaJmpD+NcAAAFhSURBVFjD7ZdbjoJAFAUbfKEIylsFBRREHbX3v7sxfTtxA/Uxk1ALqB8qtw9qZGTkfzBrEtQXB1p3oK929IcJpVtXWpPC6VZ825zxTVbiO8wYX+SK76QYTqJzI6i+g/hW0Pe478S3zxifH4iv8hjfMDc65wrV3GvDMmZr3qSM712Ib3FmfI2t+ZgzvqdjdPMbVHOnDSF0Uh+25suDrbmDjsvL1vyEav6xx6WBal6Ir3gzvtTWvJ0yvnYpvn7N+Bpb80C9baHxBb6CqOW43BVFb279TGGU5lqtOeHAFSOcQ+7BFHyXe9KFSciNDiG7cLNI8EpN13h1vo8xeiGcGjOmBTlo5Mqik0veAbrx15xu3A/IKSKvPTmWZF2jc072P9145H4nMfsPVWKNZ3s7xLDGvQqcikINjlkhXtKNpxvb+BR7D+352XmUMT+KsVUYN3N+EsWRfBovFYnX+mpkZOSv8Qvxhkf6bCYPxwAAAABJRU5ErkJggg==' mode='aspectFit' class='back-home-return'></image> </view> <view class="line" wx:if='{
{navibarData.showBack && navibarData.showCapsule}}'></view> <view class="title-bar-icon" bindtap='_backhome' wx:if='{
{navibarData.showCapsule}}'> <image wx:if="{
{navibarData.bgTransparent&&navibarData.iconColor == 'white'}}" src='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFAAAABQCAMAAAC5zwKfAAAAXVBMVEUAAAD///9RKvvlAAAAHnRSTlMA9kNVhvo95i4VAuzgsHxjWhwH0Me9uaugcE82JiScUXyNAAABNElEQVRYw+3Wx3KEMBBF0YYZRYY4Oen/P9MuyviBEVNluhcOuuuno21T6tfW3e+dIOfOKgR1dlJeXoS+IhfysvBRlst6EPkeRFkPIt+DKOtB5HsQZT2IfA8i1+OL8PgiPDkRHl+EJyfC44vw5ER4fBGenAiPL8KTE+HxRXhyIjy+CE9OhMcX4cmJ8PgiPElRw1sr6rHnTWBnPKE2CNQS8ju+t/M0yh6Ki67WWpW+FAdLszZrwU3/PIEJ/O+gKrfvlUoKNJb6rBECm2HQCIFuGDghEIsEJvDvgAYL8z0wj89PWJzii5zitfF5jUW9eNXEO0Zvlg6DLnoDHWmpZzZfK02jtJovsictVqvZ+kaTbrM/VU0vsvvpunzQlx7ldLG39DKvr9uhqnEUyTXV5+SqPaVSP683QHRHUsVUZh0AAAAASUVORK5CYII=' mode='aspectFit' class='back-home'></image> <image wx:else src='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFAAAABQCAMAAAC5zwKfAAAAXVBMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC5BxTwAAAAHnRSTlMA9kNVhvo95i4VAuzgsHxjWhwH0Me9uaugcE82JiScUXyNAAABNElEQVRYw+3Wx3KEMBBF0YYZRYY4Oen/P9MuyviBEVNluhcOuuuno21T6tfW3e+dIOfOKgR1dlJeXoS+IhfysvBRlst6EPkeRFkPIt+DKOtB5HsQZT2IfA8i1+OL8PgiPDkRHl+EJyfC44vw5ER4fBGenAiPL8KTE+HxRXhyIjy+CE9OhMcX4cmJ8PgiPElRw1sr6rHnTWBnPKE2CNQS8ju+t/M0yh6Ki67WWpW+FAdLszZrwU3/PIEJ/O+gKrfvlUoKNJb6rBECm2HQCIFuGDghEIsEJvDvgAYL8z0wj89PWJzii5zitfF5jUW9eNXEO0Zvlg6DLnoDHWmpZzZfK02jtJovsictVqvZ+kaTbrM/VU0vsvvpunzQlx7ldLG39DKvr9uhqnEUyTXV5+SqPaVSP683QHRHUsVUZh0AAAAASUVORK5CYII=' mode='aspectFit' class='back-home'></image> </view> </view> <view style="flex-grow:1;height:100%;background-color: transparent; display: flex; justify-content:{
{
navibarData.iconData.align?(navibarData.iconData.align==='right'?'flex-end':'flex-start'):'flex-start'}};"> <view style="display: flex;align-items: center;height: 100%;"> </view> </view> <view style="width:{
{
menuButtonInfo.width}}px;height:100%;background-color: transparent;"></view> <view class='nav-titleContainer'> <view wx:if="{
{navibarData.bgTransparent}}" class="nav-title" style="color:{
{
navibarData.titleColor}}">{
{navibarData.title}}</view> <view wx:else class="nav-title">{
{navibarData.title}}</view> </view> </view> </template>
component/navbar.wxss
/* 顶部要固定定位 */ .nav-wrap {
position: fixed; width: 100%; top: 0; z-index: 99; background: #ffffff; } /* 标题要居中 */ .nav-titleContainer {
display: flex; flex-direction: row; justify-content: center; align-items: center; position: absolute; top:0; left:0; height: 100%; width: 100%; pointer-events: none; } .nav-title {
margin: 0 180rpx; text-align: center; /* width: 50%; */ overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 36rpx; color: #000000; font-weight: 600; z-index: -1; } .back-home {
width: 40rpx; height: 40rpx; cursor: pointer; } .back-home-return {
width: 40rpx; height: 40rpx; cursor: pointer; } .title-bar-group {
border: 1rpx solid rgba(255,255,255,0.25); background: rgba(0,0,0,0.12); border-radius: 32rpx; display: flex; height: 64rpx; width: 174rpx; box-sizing: border-box; align-items:center; overflow: hidden; } .title-bar-group.only-group-icon {
border: none; background: transparent; width: 87rpx; } .title-bar-group.no-group-icon {
border: none; background: transparent; width: 0rpx; } .title-bar-group.no-group-icon + .nav-titleContainer {
justify-content:flex-start; } .title-bar-group.no-group-icon + .nav-titleContainer .nav-title {
margin: 0 180rpx 0 12rpx; text-align:left; } .title-bar-icon {
flex: auto; display:flex; align-items:center; justify-content:center; height:100%; } .line{
height: 38rpx; border-left: 1px solid rgba(255,255,255,0.12); } .title-bar {
display: flex; justify-content: space-between; align-items: center; margin: 0 20rpx; position: relative; } .b-nav-wrap.nav-wrap {
background: #fff; } .b-nav-wrap .nav-title {
color: #111; } .b-nav-wrap .title-bar-group {
border: 1rpx solid rgba(0,0,0,0.12); background: #ffffff; } .b-nav-wrap .line{
border-left: 1px solid rgba(0,0,0,0.12); } .b-nav-wrap .title-bar-group.only-group-icon {
border: none; background: transparent; width: 87rpx; } .b-nav-wrap .title-bar-group.no-group-icon {
border: none; background: transparent; width: 0rpx; } .b-nav-wrap.nav-wrap.transparent-bg, .b-nav-wrap.nav-wrap.transparent-bg .title-bar-group {
background: transparent; }
6. 原理分析
wx.getSystemInfoSync();
// 获取到状态栏的信息
wx.getMenuButtonBoundingClientRect();
// 获取胶囊的信息
function getStatusBarHeight() {
let res = wx.getSystemInfoSync() let customTitleBarHeight; try {
const menuInfo = wx.getMenuButtonBoundingClientRect(); // 获取胶囊的信息 if (equalVersion(res.version, "7.0.3")) {
customTitleBarHeight = menuInfo.height + (menuInfo.top - res.statusBarHeight) * 2; } else {
customTitleBarHeight = menuInfo.height + menuInfo.top * 2; } } catch (e) {
customTitleBarHeight = 48; } if (res.model.indexOf("iPhone") !== -1) {
customTitleBarHeight = 44; } return {
statusBarHeight: res.statusBarHeight, // 状态栏的高度 titleBarHeight: customTitleBarHeight, // title的高度 } };
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/126895.html