一、前言
-
微信小程序中的导航栏,因官方限制,使用不够灵活,故使用自定义导航栏,可实现一些特殊需求.
-
例如:
图标返回或跳转、文字返回或跳转、logo展示、下拉菜单、搜索、tab切换、二维码扫描
等场景
二、注意事项
注意事项、1
- 需要在
app.json的window属性
设置全局自定义导航或在页面.json
设置页面自定义导航
json
"window": {
"navigationStyle":"custom",
},
注意事项、2
- 需要在子组件中开启多slot支持
php
Component({
options: {
multipleSlots: true // 在组件定义时的选项中启用多slot支持
},
})
注意事项、3
- 获取状态栏高度及计算总高度需要在
attached
生命周期中进行
注意事项、4
- 文章内容兼容部分场景及需求,具体左右间距根据业务中的ui设计或实际需求自行调整
三、代码注释详解
- 使用父组件传入的
navBgc
、navColor
控制背景色
及字体
backIcon
控制图标的显隐
,backText
控制文字的显隐
navBarLeft
与navBarCenter
两个插槽分别控制左侧及中间的显示内容
- 通过
wx.getSystemInfoSync()
获取状态栏相关信息,statusBarHeight
属性为状态栏高度 - 通过
wx.getMenuButtonBoundingClientRect()
获取胶囊相关信息,top
属性为胶囊上部高度 - 利用公式
(胶囊上部全部高度-状态栏高度)*2 + 胶囊高度 = 导航栏高度(不包含状态栏)
计算出导航栏高度
子组件wxml
xml
<!--components/HeadNav/HeadNav.wxml-->
<view class="navBox" style="background-color:{{navBgc}};color:{{navColor}}">
<!-- 状态栏占位,即电量、时间等状态信息,statusBarHeight为状态栏高度 -->
<!-- 此处文字仅做演示用,状态栏只做占位使用,使用时清除文字即可 -->
<view class="statusBar" style="height:{{statusBarHeight}}px;">这是个状态栏,仅做演示使用</view>
<!-- 导航栏内容,navBarHeight为计算出的导航栏高度 -->
<view class="navBar" style="height:{{navBarHeight}}px">
<!-- 可处理回退图标、返回文字、扫描功能及其它左侧相关需求 -->
<view class="navBarLeft">
<!-- 图标或文字显示时,默认回退上一页,也可根据path传递需要跳转的路径 -->
<image src="/resource/imgs/backIcon.png" mode="heightFix" bindtap="back" wx:if="{{backIcon}}" />
<view bindtap="back" wx:if="{{backText}}">返回</view>
<slot name="navBarLeft"></slot>
</view>
<!-- 可处理标题、logo、搜索栏、tab切换等其它中间位置需求 -->
<view class="navBarCenter">
<view>{{navTitle}}</view>
<slot name="navBarCenter"></slot>
</view>
<!-- 右侧占位 -->
<view></view>
</view>
</view>
子组件js
php
// components/HeadNav/HeadNav.js
Component({
options: {
multipleSlots: true // 在组件定义时的选项中启用多slot支持
},
// 页面的初始数据
data: {
// 状态栏高度
statusBarHeight: null,
// 导航栏高度
navBarHeight: null
},
properties: {
// 是否显示回退图标
backIcon: {
type: Boolean,
value: true
},
// 是否显示回退文字
backText: {
type: Boolean,
value: false
},
// 标题
navTitle: {
type: String,
value: '标题'
},
// 背景色
navBgc: {
type: String,
value: '#00b26a'
},
// 字体颜色
navColor: {
type: String,
value: 'white'
},
},
lifetimes: {
// 此生命周期在组件实例进入页面节点树时执行
attached() {
// 判断获取微信小程序胶囊API是否可用
if (wx.canIUse('getMenuButtonBoundingClientRect')) {
// 获取状态栏高度(电量时间通知等信息) 单位px
let sysInfo = wx.getSystemInfoSync();
// 获取微信小程序胶囊布局位置信息
let rect = wx.getMenuButtonBoundingClientRect();
// 通过下列公式保证胶囊位于除状态栏外的竖向中间位置,多机型适配
// (胶囊上部全部高度-状态栏高度)*2 + 胶囊高度 = 导航栏高度(不包含状态栏)
let navBarHeight = (rect.top - sysInfo.statusBarHeight) * 2 + rect.height;
this.setData({
statusBarHeight: sysInfo.statusBarHeight,
navBarHeight: navBarHeight
})
} else {
wx.showToast({
title: '您的微信版本过低,界面可能会显示不正常',
icon: 'none',
duration: 4000
});
}
}
},
methods: {
// 回退图标或返回文字
back() {
//此处可依照需求自行扩展其他跳转形式,如tabbar,指定页面等等,本次仅演示回退
wx.navigateBack()
},
},
})
子组件css(附css/sass两版)
1.sass
css
.navBar{
// left和center同时存在则两边靠边中间自适应(默认两边靠边中间自适应)
// left和center只存在一个则居中显示
// 即三盒子与一盒子得切换关系
display: flex;
justify-content: space-between;
align-items: center;
// 左右间距可根据需求自由调整
// 此次演示暂定下列数值,具体数值可根据ui设计或视觉效果自由调整
.navBarLeft{
display: flex;
align-items: center;
margin-left: 40rpx;
image{
width: 50rpx;
height: 50rpx;
}
}
.navBarCenter{
margin-right: 120rpx;
display: flex;
align-items: center;
}
}
input{
margin-right: 60rpx;
width: 300rpx;
height: 60rpx;
background-color: #fff;
border-radius: 50rpx;
padding-left: 20rpx;
font-size: 28rpx;
position: relative;
::after{
content: '搜索';
position: absolute;
right: 30rpx;
top: 50%;
transform: translateY(-50%);
background-color: #fff;
color: #00b26a;
}
}
2.css
css
@charset "UTF-8";
.navBar {
display: flex;
justify-content: space-between;
align-items: center;
}
.navBar .navBarLeft {
display: flex;
align-items: center;
margin-left: 40rpx;
}
.navBar .navBarLeft image {
width: 50rpx;
height: 50rpx;
}
.navBar .navBarCenter {
margin-right: 120rpx;
display: flex;
align-items: center;
}
input {
margin-right: 60rpx;
width: 300rpx;
height: 60rpx;
background-color: #fff;
border-radius: 50rpx;
padding-left: 20rpx;
font-size: 28rpx;
position: relative;
}
input ::after {
content: '搜索';
position: absolute;
right: 30rpx;
top: 50%;
transform: translateY(-50%);
background-color: #fff;
color: #00b26a;
}
四、演示场景使用代码
父组件wxml
xml
<!--pages/login/login.wxml-->
<HeadNav path="pages/index/index">
<view slot="navBarLeft"></view>
<view slot="navBarCenter"></view>
</HeadNav>
<view>上面 ↑ 是 组件默认 状态</view>
<HeadNav navTitle="标题" navBgc="#fbc115" navColor="#2d7cee" backIcon="{{false}}" backText="{{true}}">
<view slot="navBarLeft"></view>
<view slot="navBarCenter"></view>
</HeadNav>
<view>上面 ↑ 是 回退图标隐藏左侧文字返回 的状态</view>
<HeadNav navTitle="" navBgc="aqua" navColor="yellow" backIcon="{{false}}">
<view slot="navBarLeft">
<image src="/resource/imgs/logo.png" class="navBarLeftImg" mode="heightFix" />
</view>
<view slot="navBarCenter">
<input type="text" placeholder="请输入搜索内容"/>
</view>
</HeadNav>
<view>上面 ↑ 是 左logo中间搜索 的状态</view>