小程序自定义导航自适应组件

小程序自定义导航自适应组件小程序开发中 有时我们不需要自带的导航栏 那就需要自己写一个这样的导航栏

大家好,欢迎来到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

(0)
上一篇 2025-09-14 22:33
下一篇 2025-09-14 22:45

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信