微信小程序自定义导航栏(模板化)


Posted in Javascript onNovember 15, 2019

前段时间写过一篇关于微信小程序自定义导航栏的自定义组件,但是对于分享页有一定的bug
这次用模板化又搞了一遍 优化了下Android与IOS 显示更接近微信原生的导航栏,以及修复分享页面不显示返回首页按钮
如果大家不习惯模板化的话可以 针对自己的需求拿以前封装的组件化做一些修改
微信小程序自定义导航栏(组件化)

CustomNavBar.wxml

<template name="CustomNavBar">
 <block wx:if="{{ showNavBar }}">

 <!-- 自定义导航栏悬浮时,卡空行 -->
 <block wx:if="{{ needFixed }}">
  <view style="position: relative; width: 100%; height: {{ navHeight }}px;"></view>
 </block>

 <view class="custom-navbar-con relative {{ iOS ? ' ios ' : ' android ' }}" style="height: {{ navHeight }}px; {{ needFixed ? 'position: fixed; top: 0;' : '' }}">
  <view class="custom-navbar-statusbar-con relative" style="height: {{ statusBarHeight }}px;"></view>
  <view class="custom-navbar-content relative" style="height: {{ navHeight - statusBarHeight }}px;">

  <!-- iOS端的导航栏显示方式 -->
  <block wx:if="{{ navTitle && navTitle.length > 0 }}">
   <view class="custom-navbar-title ios">{{ navTitle }}</view>
  </block>

  <block wx:if="{{ showLeftMenu }}">
   <view class="custom-navbar-left-menu-con clearfix" style="top: {{ navRightMenuRect.top - statusBarHeight - 1 }}px; left: {{ winWidth - navRightMenuRect.right }}px; height: {{ navRightMenuRect.height + 2 }}px;">
   <block wx:if="{{ showBackBtn }}">
    <view class="custom-navbar-icon-btn pull-left back" style="height: {{ navRightMenuRect.height }}px" bindtap="customNavBarBack">
    <image class="icon" src="../../image/icon-nav-back.png" mode="aspectFit" style="width: {{ navRightMenuRect.height }}px;" />
    <text class="text"></text>
    </view>
   </block>

   <block wx:if="{{ showHomeBtn }}">
    <view class="custom-navbar-icon-btn pull-left home" style="height: {{ navRightMenuRect.height }}px" bindtap="customNavBarBackToHome">
    <image class="icon" src="../../image/icon-nav-home.png" mode="aspectFit" style="width: {{ navRightMenuRect.height }}px;" />
    <text class="text"></text>
    </view>
   </block>

   <!-- android端的导航栏显示方式 -->
   <block wx:if="{{ navTitle && navTitle.length > 0 }}">
    <view class="custom-navbar-title android pull-left" style="line-height: {{ navRightMenuRect.height - 2 }}px;">{{ navTitle }}</view>
   </block>
   </view>
  </block>
  </view>
 </view>
 </block>
</template>

CustomNavBar.wxss

.custom-navbar-con { position: relative; width: 100%; background-color: white; z-index: 9999; }
.custom-navbar-con .custom-navbar-statusbar-con { width: 100%; }
.custom-navbar-con .custom-navbar-content { width: 100%; }
.custom-navbar-con .custom-navbar-left-menu-con { position: absolute; }
.custom-navbar-con .custom-navbar-left-menu-con .custom-navbar-icon-btn { height: 100%; border-radius: 200px; border: 1px solid rgba(220, 220, 220, 0.6); }
.custom-navbar-con .custom-navbar-left-menu-con .custom-navbar-icon-btn .icon { height: 90%; margin-top: 2.5%; }
.custom-navbar-con .custom-navbar-left-menu-con .custom-navbar-icon-btn .text { font-size: 27rpx; }
.custom-navbar-con .custom-navbar-left-menu-con .custom-navbar-icon-btn.back { border: none; }
.custom-navbar-con .custom-navbar-left-menu-con .custom-navbar-icon-btn.back~.custom-navbar-icon-btn.home { margin-left: 10rpx; }
.custom-navbar-con .custom-navbar-left-menu-con .custom-navbar-icon-btn.switch-shop { padding-left: 5px; padding-right: 25rpx; }


.custom-navbar-con.ios .custom-navbar-title.android { display: none; }
.custom-navbar-con.android .custom-navbar-title.ios { display: none; }
.custom-navbar-con .custom-navbar-title.ios { font-weight: bold; text-align: center; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); -webkit-transform: translate(-50%, -50%); }
.custom-navbar-con .custom-navbar-title.android { padding-left: 30rpx; }```

CustomNavBar.js

```javascript
module.exports = function(PageInstance) {
 let App = getApp()

 let _tplData = {
 _CustomNavBar_: {
  navRightMenuRect: App.NavRightMenuRect,
  navRightMenuCenterY: App.NavRightMenuCenterY,
  statusBarHeight: App.StatusBarHeight,
  winWidth: App.WinWidth,
  winHeight: App.WinHeight,
  iOS: App.iOS,

  navTitle: '', // 当前只合适短标题,如需长标题,建议隐藏自定义导航栏,自定义展示
  navHeight: App.CustomNavHeight,

  needFixed: false,

  showNavBar: !App.NavRightMenuRect ? false : true,
  showLeftMenu: true,
  showBackBtn: true,
  showHomeBtn: false
 }
 }

 let _tplMethods = {
 customNavBarBack() {
  wx.navigateBack()
 },
 customNavBarBackToHome() {
  let url = '/pages/index/index'
  wx.reLaunch({
  url: url
  })
 }
 }
 let isIndexPage = !!(PageInstance.route == 'pages/index/index')
 let pages = getCurrentPages()
 if (pages.length == 1) {
 _tplData._CustomNavBar_.showBackBtn = false
 _tplData._CustomNavBar_.showHomeBtn = !isIndexPage
 }

 // 每个页面 可单独配置自定义导航栏
 if (PageInstance.data.CustomNavBarConfig) {
 Object.assign(_tplData._CustomNavBar_, PageInstance.data.CustomNavBarConfig)
 }

 // !!!! 最后执行
 // 当无法获取到右上角按钮胶囊的布局位置时,强制设置自定义导航栏为隐藏状态
 if (!App.NavRightMenuRect) {
 _tplData._CustomNavBar_.showNavBar = false
 }

 Object.assign(PageInstance, _tplMethods)
 PageInstance.setData(_tplData)
 return this
}

app.js的配置

// 自定义导航栏
import CustomNavBar from './template/CustomNavBar/CustomNavBar';

 App({
 //自定义 模板式 组件
 CustomNavBar,
 
 // 系统信息
  WinWidth: 0,
  WinHeight: 0,
  StatusBarHeight: 0,
  PixelRatio: 1,
  SystemFullName: '',
  SystemVersion: '',
  SystemSDKVersion: '',

  //自定义导航栏相关
  NavRightMenuRect: null,
  NavRightMenuCenterY: 0,
  CustomNavHeight: 0,
  
 onLaunch: function (options) {
 let self = this
 let systemInfo = wx.getSystemInfoSync()
 self.iOS = systemInfo.platform === 'ios'
 self.isDebug = systemInfo.platform === 'devtools'
 if (self.isDebug) {
  // 单纯为了在开发工具下调试 自定义导航栏
  // 开发工具下不存在App版本号的区分
  systemInfo.version = '7.0.0'
 }
 self.WinWidth = systemInfo.windowWidth
 self.WinHeight = systemInfo.windowHeight
 self.StatusBarHeight = systemInfo.statusBarHeight
 // 部分小程序库版本没有返回状态栏高度
 if (!self.StatusBarHeight) {
  self.StatusBarHeight = 20
 }
 self.PixelRatio = Math.max(systemInfo.pixelRatio, 2)
 self.SystemFullName = systemInfo.system
 self.SystemVersion = systemInfo.version
 self.SystemSDKVersion = systemInfo.SDKVersion

 // app.json全局配置的自定义导航栏的话,客户端需求版本为6.6.0
 // 每个页面 单独配置的自定义导航栏的话,客户端需求版本为7.0.0
 // wx.getMenuButtonBoundingClientRect方法,要求基础库版本为2.1.0
 if (self.compareVersion(self.SystemVersion, '6.6.0') >= 0) {
  // 官方的6.6.0版本以上客户端,最低基础库版本为1.9.4
  // 6.6.0以上且[1.9.4 - 2.1.0]范围内的机型无法使用wx.getMenuButtonBoundingClientRect
  // 所以手动写死非全面屏手机的适配胶囊布局位置
  self.NavRightMenuRect = {
  top: 26,
  bottom: 58,
  right: self.WinWidth - 10,
  width: 87,
  height: 32
  }
  // 如果系统信息返回的状态栏高度大于20,认为是全面屏手机
  if (self.StatusBarHeight > 20) {
  self.NavRightMenuRect.top = 50
  self.NavRightMenuRect.bottom = 82
  }

  // 2019年08月21日22:09:22
  // 微信小程序库出现bug,导致部分机型wx.getMenuButtonBoundingClientRect无返回值
  // 所以在这之前先默认写死一个NavRightMenuRect,防止全局的自定义导航栏已经隐藏了但是无法显示自定义导航栏
  // 详见https://developers.weixin.qq.com/community/develop/doc/00062238d78e880aedd88b72351c00
  if (wx.getMenuButtonBoundingClientRect) {
  let NavRightMenuRect = wx.getMenuButtonBoundingClientRect()
  self.NavRightMenuRect = {
   top: NavRightMenuRect.top,
   bottom: NavRightMenuRect.bottom,
   right: NavRightMenuRect.right,
   width: NavRightMenuRect.width,
   height: NavRightMenuRect.height
  }
  }

  self.NavRightMenuCenterY = self.NavRightMenuRect.top + self.NavRightMenuRect.height / 2
  self.CustomNavHeight = self.NavRightMenuRect.bottom + (self.NavRightMenuRect.top - self.StatusBarHeight)
 } else {
  self.NavRightMenuRect = null
  self.CustomNavHeight = 0
 }
 },
 
  // 比较两个版本号
 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
 } 
    
}),

假如在index 页面引用

index.wxml

<!-- 自定义NavBar -->
<import src="../../template/CustomNavBar/CustomNavBar.wxml" />
<template is="CustomNavBar" data="{{ ..._CustomNavBar_ }}"></template>

index.js

onLoad: function(options) {
  new App.CustomNavBar(this)
 }

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
js检查页面上有无重复id的实现代码
Jul 17 Javascript
js完美的div拖拽实例代码
Jan 22 Javascript
JavaScript中九种常用排序算法
Sep 02 Javascript
js实现点击链接后延迟3秒再跳转的方法
Jun 05 Javascript
js创建数组的简单方法
Jul 27 Javascript
JavaScript累加、迭代、穷举、递归等常用算法实例小结
May 08 Javascript
使用webpack4编译并压缩ES6代码的方法示例
Apr 24 Javascript
用vscode开发vue应用的方法步骤
May 06 Javascript
angular6开发steps步骤条组件
Jul 04 Javascript
vue element-ui实现input输入框金额数字添加千分位
Dec 29 Javascript
Element Breadcrumb 面包屑的使用方法
Jul 26 Javascript
一篇文章带你从零快速上手Rollup
Sep 07 Javascript
在node环境下parse Smarty模板的使用示例代码
Nov 15 #Javascript
微信小程序自定义头部导航栏(组件化)
Nov 15 #Javascript
create-react-app中添加less支持的实现
Nov 15 #Javascript
taro小程序添加骨架屏的实现代码
Nov 15 #Javascript
详解Angular Karma测试的持续集成实践
Nov 15 #Javascript
Javascript 类型转换、封闭函数及常见内置对象操作示例
Nov 15 #Javascript
JavaScript定时器常见用法实例分析
Nov 15 #Javascript
You might like
php判断用户是否手机访问代码
2015/06/08 PHP
PHP删除二维数组中相同元素及数组重复值的方法示例
2017/05/05 PHP
php判断/计算闰年的方法小结【三种方法】
2019/07/06 PHP
利用PHP计算有多少小于当前数字的数字方法示例
2020/08/26 PHP
PHP SESSION跨页面传递失败解决方案
2020/12/11 PHP
JQuery 中几个类选择器的简单使用介绍
2013/03/14 Javascript
js文件缓存之版本管理详解
2013/07/05 Javascript
js四舍五入数学函数round使用实例
2014/05/09 Javascript
javascript arguments使用示例
2014/12/16 Javascript
JavaScript判断字符长度、数字、Email、电话等常用判断函数分享
2015/04/01 Javascript
jQuery Ajax 上传文件处理方式介绍(推荐)
2016/06/30 Javascript
正则表达式,替换所有HTML标签的简单实例
2016/11/28 Javascript
p5.js实现斐波那契螺旋的示例代码
2018/03/22 Javascript
node获取客户端ip功能简单示例
2019/08/24 Javascript
Vue 用Vant实现时间选择器的示例代码
2019/10/25 Javascript
vue+render+jsx实现可编辑动态多级表头table的实例代码
2020/04/01 Javascript
vue项目开启Gzip压缩和性能优化操作
2020/10/26 Javascript
[02:20]2014DOTA2西雅图邀请赛 MVP外卡赛首胜采访
2014/07/09 DOTA
python实现颜色rgb和hex相互转换的函数
2015/03/19 Python
python实现的简单文本类游戏实例
2015/04/28 Python
Python使用chardet判断字符编码
2015/05/09 Python
Python制作简易注册登录系统
2016/12/15 Python
pip安装时ReadTimeoutError的解决方法
2018/06/12 Python
selenium设置proxy、headers的方法(phantomjs、Chrome、Firefox)
2018/11/29 Python
基于OpenCV python3实现证件照换背景的方法
2019/03/22 Python
Python面向对象程序设计类的多态用法详解
2019/04/12 Python
Python安装与基本数据类型教程详解
2019/05/29 Python
自定义Django默认的sitemap站点地图样式
2020/03/04 Python
美国知名玩具品牌:Melissa & Doug
2016/08/16 全球购物
大学生的自我鉴定范文
2014/01/21 职场文书
小学校园广播稿
2015/08/18 职场文书
导游词之塘栖古镇
2019/12/04 职场文书
MySQL笔记 —SQL运算符
2022/01/18 MySQL
Redis命令处理过程源码解析
2022/02/12 Redis
python套接字socket通信
2022/04/01 Python
Win11电脑显示本地时间与服务器时间不一致怎么解决?
2022/04/05 数码科技