[前端] uniapp微信小程序自定义导航栏的全过程

2170 0
王子 2022-10-21 15:23:55 | 显示全部楼层 |阅读模式
目录

    前言那么标题栏的高度我们怎么获取呢?献上源码:组件使用:效果图:总结


前言

相信很多小伙伴在使用uniapp进行多端开发的时候呢,在面对一些奇葩的业务需求的时候,uniapp给我们提供的默认导航栏已经不能满足我们的业务需求了,这个时候就需要我们自己自定义导航栏使用啦。
当然uniapp也给我们提供了很多的自定义导航栏的插件供大家使用,今天也给大家分享一个我自己写的导航栏啦,希望大家多多指点
首先我们在自定义导航栏的时候,我们需要知道头部的导航栏有哪几部分组成,那么我们以微信小程序为例


可以看到在微信小程序中,我们的头部导航栏其实受到右上角胶囊的限制比较大,这个时候我们自定义的导航栏,需要做到标题于胶囊水平对齐,那其实这个时候整个头部其实主要又:状态栏的高度+标题栏的高度组成。
状态栏的高度我们可以通过uni.getSystemInfoSync().statusBarHeight来获取。

那么标题栏的高度我们怎么获取呢?

其实要想定义标题栏的高度,我们需要知道这个胶囊的位置,在小程序中我们可以使用wx.getMenuButtonBoundingClientRect()获取关于胶囊的信息


获取到的胶囊的top,left,right分别对应胶囊的上边界,左边界,右边界相对于屏幕左上角的起点的位置,所以我们是不是可以用(胶囊上边界距离顶部的距离 - 状态栏的高度)*2+胶囊的高度,就是标题栏的高度呢?然后再在标题栏里面添加一个文本区让他的高度等于胶囊的高度,实现flex布局的上下居中是不是就搞定了呢?
以上呢其实针对小程序平台的导航栏讲解,那么既然使用uniapp,就会考虑到多端情况
那么其实我们使用uniapp获取到的状态栏在h5,小程序和app原生都是有效的,h5网页中一般我们都是直接采用浏览器内核给我们内置的网页导航栏,就是一个头部,没有过多的要求,而且浏览器不同,给我们提供的头部导航也不一样。
而对于app端,我们没有了像微信小程序中那种让人心烦的胶囊之后,我们只需要知道状态栏的高度,然后加上自己业务需求的标题栏样式和标题栏高度就行啦
所以我们在进行自定义导航栏封装的时候就要对代码进行条件编译啦。那么我这里呢是把微信小程序做了单独的处理,微信小程序之外的平台看作是统一状态

献上源码:

首先我们把获取设备信息的代码封装到一个统一的js文件里面,这样方便我们在组件中获取也方便我们在页面中获取。

  1. /**
  2. * 此js文件管理关于当前设备的机型系统信息
  3. */
  4. const systemInfo = function() {
  5.         /****************** 所有平台共有的系统信息 ********************/
  6.         // 设备系统信息
  7.         let systemInfomations = uni.getSystemInfoSync()
  8.         // 机型适配比例系数
  9.         let scaleFactor = 750 / systemInfomations.windowWidth
  10.         // 当前机型-屏幕高度
  11.         let windowHeight = systemInfomations.windowHeight * scaleFactor //rpx
  12.         // 当前机型-屏幕宽度
  13.         let windowWidth = systemInfomations.windowWidth * scaleFactor //rpx
  14.         // 状态栏高度
  15.         let statusBarHeight = (systemInfomations.statusBarHeight) * scaleFactor //rpx
  16.         // 导航栏高度  注意:此导航栏高度只针对微信小程序有效 其他平台如自定义导航栏请使用:状态栏高度+自定义文本高度
  17.         let navHeight = 0 //rpx
  18.         // console.log(windowHeight,'哈哈哈哈哈');
  19.         /****************** 微信小程序头部胶囊信息 ********************/
  20.         // #ifdef MP-WEIXIN
  21.         const menuButtonInfo = wx.getMenuButtonBoundingClientRect()
  22.         // 胶囊高度
  23.         let menuButtonHeight = menuButtonInfo.height * scaleFactor //rpx
  24.         // 胶囊宽度
  25.         let menuButtonWidth = menuButtonInfo.width * scaleFactor //rpx
  26.         // 胶囊上边界的坐标
  27.         let menuButtonTop = menuButtonInfo.top * scaleFactor //rpx
  28.         // 胶囊右边界的坐标
  29.         let menuButtonRight = menuButtonInfo.right * scaleFactor //rpx
  30.         // 胶囊下边界的坐标
  31.         let menuButtonBottom = menuButtonInfo.bottom * scaleFactor //rpx
  32.         // 胶囊左边界的坐标
  33.         let menuButtonLeft = menuButtonInfo.left * scaleFactor //rpx
  34.         // 微信小程序中导航栏高度 = 胶囊高度 + (顶部距离 - 状态栏高度) * 2
  35.         navHeight = menuButtonHeight + (menuButtonTop - statusBarHeight) * 2
  36.         // #endif
  37.         // #ifdef MP-WEIXIN
  38.         return {
  39.                 scaleFactor,
  40.                 windowHeight,
  41.                 windowWidth,
  42.                 statusBarHeight,
  43.                 menuButtonHeight,
  44.                 menuButtonWidth,
  45.                 menuButtonTop,
  46.                 menuButtonRight,
  47.                 menuButtonBottom,
  48.                 menuButtonLeft,
  49.                 navHeight
  50.         }
  51.         // #endif
  52.         // #ifndef MP-WEIXIN
  53.         return {
  54.                 scaleFactor,
  55.                 windowHeight,
  56.                 windowWidth,
  57.                 statusBarHeight
  58.         }
  59.         // #endif
  60. }
  61. export {
  62.         systemInfo
  63. }
复制代码
然后我们定义一个导航栏组件

  1. /*
  2. * 注意:
  3. * 1、在传入宽度或者高度时,如果是Number数据,传入的值为px大小,无需带单位,组件自动计算
  4. * 2、在使用此导航栏时,建议传入UI规定的导航栏高度,此高度只针对除微信小程序的其他平台有效,微信小程序的导航栏高度,组件自计算
  5. */
  6. <template>
  7.         <view>
  8.                 <!-- 微信小程序头部导航栏 -->
  9.                 <!-- #ifdef MP-WEIXIN -->
  10.                 <view class="wx-head-mod" :style="{height:navHeight+'rpx',backgroundColor:navBackgroundColor}">
  11.                         <view class="wx-head-mod-nav" :style="{height:navigationBarHeight+'rpx',top:statusBarHeight+'rpx'}">
  12.                                 <view class="wx-head-mod-nav-content"
  13.                                         :style="{height:customHeight+'rpx',justifyContent:textAlign === 'center'?'center':'left'}">
  14.                                         <!-- 文本区 -->
  15.                                         <view class="wx-head-mod-nav-content-mian"
  16.                                                 :style="{width:navTextWidth,lineHeight:customHeight + 'rpx',paddingLeft:textPaddingLeft*scaleFactor+'rpx',fontSize:fontSize*scaleFactor+'rpx',fontWeight:fontWeight,color:titleColor}">
  17.                                                 {{textContent}}
  18.                                         </view>
  19.                                         <!-- 返回按钮 -->
  20.                                         <view class="wx-head-mod-nav-content-back" :style="{display:isBackShow?'flex':'none'}"
  21.                                                 @click="backEvent">
  22.                                                 <view class="wx-head-mod-nav-content-back-img"
  23.                                                         :style="{width:backImageWidth*scaleFactor+'rpx',height:backImageHeight*scaleFactor+'rpx'}">
  24.                                                         <image :src="backImageUrl" mode="" style="width: 100%;height: 100%;"></image>
  25.                                                 </view>
  26.                                         </view>
  27.                                 </view>
  28.                         </view>
  29.                 </view>
  30.                 <!-- #endif -->
  31.                 <!-- 除微信小程序之外的其他设备 -->
  32.                 <!-- #ifndef MP-WEIXIN -->
  33.                 <view class="other-head-mod"
  34.                         :style="{height:navHeightValue*scaleFactor+statusBarHeight+'rpx',backgroundColor:navBackgroundColor}">
  35.                         <view class="other-head-mod-mian"
  36.                                 :style="{height:navHeightValue*scaleFactor+'rpx',justifyContent:textAlign === 'center'?'center':'left'}">
  37.                                 <!-- 返回按钮 -->
  38.                                 <view class="other-head-mod-mian-back" v-show="isBackShow" @click="backEvent">
  39.                                         <view class="other-head-mod-mian-back-img"
  40.                                                 :style="{width:backImageWidth*scaleFactor+'rpx',height:backImageHeight*scaleFactor+'rpx'}">
  41.                                                 <image :src="backImageUrl" mode="" style="width: 100%;height: 100%;"></image>
  42.                                         </view>
  43.                                 </view>
  44.                                 <!-- 标题 -->
  45.                                 <view class="other-head-mod-mian-title" :style="{width:windowWidth - 184+'rpx',lineHeight:navHeightValue*scaleFactor+'rpx',
  46.                                         paddingLeft:textPaddingLeft*scaleFactor+'rpx',fontSize:fontSize*scaleFactor+'rpx',
  47.                                         fontWeight:fontWeight,color:titleColor}">
  48.                                         {{textContent}}
  49.                                 </view>
  50.                         </view>
  51.                 </view>
  52.                 <!-- #endif -->
  53.         </view>
  54. </template>
  55. <script>
  56.         const app = getApp()
  57.         import {systemInfo} from '@/common/system-info.js'
  58.         export default {
  59.                 name: "HeadView",
  60.                 props: {
  61.                         // 文本区域位置 left:左  center:中  
  62.                         textAlign: {
  63.                                 type: String,
  64.                                 default: 'center'
  65.                         },
  66.                         // 文本区内容
  67.                         textContent: {
  68.                                 type: String,
  69.                                 default: '哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈就啊哈哈好借好还'
  70.                         },
  71.                         // 文本区离左边的距离
  72.                         textPaddingLeft: {
  73.                                 type: Number,
  74.                                 default: 16
  75.                         },
  76.                         // 是否需要返回按钮
  77.                         isBackShow: {
  78.                                 type: Boolean,
  79.                                 default: true
  80.                         },
  81.                         // 文本区字体大小
  82.                         fontSize: {
  83.                                 type: Number,
  84.                                 default: 20 //px
  85.                         },
  86.                         // 文本区字体粗细
  87.                         fontWeight: {
  88.                                 type: Number,
  89.                                 default: 700
  90.                         },
  91.                         // 文本区返回按钮图片宽
  92.                         backImageWidth: {
  93.                                 type: Number,
  94.                                 default: 12 //px
  95.                         },
  96.                         // 文本区返回按钮图片高
  97.                         backImageHeight: {
  98.                                 type: Number,
  99.                                 default: 24 //px
  100.                         },
  101.                         // 返回按钮图标路径
  102.                         backImageUrl: {
  103.                                 type: String,
  104.                                 default: '/static/backImage.svg'
  105.                         },
  106.                         // 导航栏整体背景颜色
  107.                         navBackgroundColor: {
  108.                                 type: String,
  109.                                 default: '#2476F9'
  110.                         },
  111.                         // 标题字体颜色
  112.                         titleColor: {
  113.                                 type: String,
  114.                                 default: '#ffffff',
  115.                         },
  116.                         /******** h5端,app端需要传入自定义导航栏高度 *******/
  117.                         navHeightValue: {
  118.                                 type: Number,
  119.                                 default: 44 //px
  120.                         }
  121.                 },
  122.                 computed: {
  123.                         // 文本区宽度
  124.                         navTextWidth() {
  125.                                 if (this.textAlign === 'center') {
  126.                                         return (this.windowWidth - (this.windowWidth - this.menubarLeft) * 2) + 'rpx'
  127.                                 } else {
  128.                                         return this.menubarLeft + 'rpx'
  129.                                 }
  130.                         },
  131.                         // 文本区paddingLeft
  132.                         textPaddingleft() {
  133.                                 if (this.textAlign === 'center') {
  134.                                         return '0'
  135.                                 } else {
  136.                                         return this.textPaddingLeft + 'rpx'
  137.                                 }
  138.                         }
  139.                 },
  140.                 data() {
  141.                         return {
  142.                                 statusBarHeight: app.globalData.statusBarHeight, //状态栏高度
  143.                                 navHeight: app.globalData.navHeight, //头部导航栏总体高度
  144.                                 navigationBarHeight: app.globalData.navigationBarHeight, //导航栏高度
  145.                                 customHeight: app.globalData.customHeight, //胶囊高度
  146.                                 scaleFactor: app.globalData.scaleFactor, //比例系数
  147.                                 menubarLeft: app.globalData.menubarLeft, //胶囊定位的左边left
  148.                                 windowWidth: app.globalData.windowWidth * app.globalData.scaleFactor
  149.                         };
  150.                 },
  151.                 methods: {
  152.                         backEvent() {
  153.                                 uni.navigateBack({
  154.                                         delta: 1
  155.                                 })
  156.                         }
  157.                 },
  158.                 created() {
  159.                         /* 获取设备信息 */
  160.                         const SystemInfomations = systemInfo()
  161.                         /* 通用平台 */
  162.                         this.statusBarHeight = SystemInfomations.statusBarHeight //状态栏高度
  163.                         this.scaleFactor = SystemInfomations.scaleFactor //比例系数
  164.                         this.windowWidth = SystemInfomations.windowWidth //当前设备的屏幕宽度
  165.                         /* 微信小程序平台 */
  166.                         // #ifdef MP-WEIXIN
  167.                         this.navHeight = SystemInfomations.navHeight + SystemInfomations.statusBarHeight //头部导航栏总高度
  168.                         this.navigationBarHeight = SystemInfomations.navHeight //头部导航栏高度
  169.                         this.customHeight = SystemInfomations.menuButtonHeight //胶囊高度
  170.                         this.menubarLeft = SystemInfomations.menuButtonLeft //胶囊左边界距离左上角的距离
  171.                         // #endif
  172.                 }
  173.         }
  174. </script>
  175. <style>
  176.         /* #ifdef MP-WEIXIN */
  177.         .wx-head-mod {
  178.                 box-sizing: border-box;
  179.                 width: 100%;
  180.                 position: fixed;
  181.                 top: 0;
  182.                 left: 0;
  183.         }
  184.         .wx-head-mod-nav {
  185.                 box-sizing: border-box;
  186.                 width: 100%;
  187.                 position: absolute;
  188.                 left: 0;
  189.                 display: flex;
  190.                 justify-content: center;
  191.                 align-items: center;
  192.         }
  193.         .wx-head-mod-nav-content {
  194.                 box-sizing: border-box;
  195.                 width: 100%;
  196.                 display: flex;
  197.                 justify-content: left;
  198.                 align-items: center;
  199.                 position: relative;
  200.         }
  201.         /* 文本区 */
  202.         .wx-head-mod-nav-content-mian {
  203.                 box-sizing: border-box;
  204.                 height: 100%;
  205.                 white-space: nowrap;
  206.                 text-overflow: ellipsis;
  207.                 overflow: hidden;
  208.         }
  209.         /* 返回按钮 */
  210.         .wx-head-mod-nav-content-back {
  211.                 box-sizing: border-box;
  212.                 width: 60rpx;
  213.                 height: 100%;
  214.                 /* background-color: aqua; */
  215.                 position: absolute;
  216.                 top: 0;
  217.                 left: 32rpx;
  218.                 display: flex;
  219.                 align-items: center;
  220.                 justify-content: left;
  221.         }
  222.         .wx-head-mod-nav-content-back-img {
  223.                 box-sizing: border-box;
  224.         }
  225.         /* #endif */
  226.         /* #ifndef MP-WEIXIN */
  227.         .other-head-mod {
  228.                 box-sizing: border-box;
  229.                 width: 100%;
  230.                 position: fixed;
  231.                 top: 0;
  232.                 left: 0;
  233.         }
  234.         .other-head-mod-mian {
  235.                 box-sizing: border-box;
  236.                 width: 100%;
  237.                 display: flex;
  238.                 align-items: center;
  239.                 justify-content: left;
  240.                 position: absolute;
  241.                 left: 0;
  242.                 bottom: 0;
  243.         }
  244.         /* 返回按钮 */
  245.         .other-head-mod-mian-back {
  246.                 box-sizing: border-box;
  247.                 height: 100%;
  248.                 width: 60rpx;
  249.                 position: absolute;
  250.                 left: 32rpx;
  251.                 top: 0;
  252.                 display: flex;
  253.                 align-items: center;
  254.         }
  255.         /* 标题 */
  256.         .other-head-mod-mian-title {
  257.                 box-sizing: border-box;
  258.                 height: 100%;
  259.                 white-space: nowrap;
  260.                 text-overflow: ellipsis;
  261.                 overflow: hidden;
  262.         }
  263.         /* #endif */
  264. </style>
复制代码
组件使用:

引入组件:
  1. import HeadNav from '@/components/HeadNav.vue'
复制代码
组册组件:
  1. components:{
  2.                         HeadNav
  3.                 },
复制代码
  1. <template>
  2.         <view class="content">
  3.                 <head-nav></head-nav>
  4.                 <view class="content-main"></view>
  5.         </view>
  6. </template>
复制代码
效果图:

微信小程序:


h5:


app:


在项目里面没有针对h5时候需要导航栏做特别的限制,如果实际开发中在h5端不需要此导航栏,请在模版上面针对h5页面加入条件编译即可。

总结

到此这篇关于uniapp微信小程序自定义导航栏的文章就介绍到这了,更多相关uniapp自定义导航栏内容请搜索中国红客联盟以前的文章或继续浏览下面的相关文章希望大家以后多多支持中国红客联盟!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

中国红客联盟公众号

联系站长QQ:5520533

admin@chnhonker.com
Copyright © 2001-2025 Discuz Team. Powered by Discuz! X3.5 ( 粤ICP备13060014号 )|天天打卡 本站已运行