最近在微信小程序项目中有webview嵌入活动页的需求,发现微信小程序没法配置导航栏,只能使用自定义组件模拟实现导航栏,所以打算自己写一个。
配置自定义导航
首先贴上官方文档
developers.weixin.qq.com/miniprogram…
{
"component": true,
"usingComponents": {
"navbar": "/components/navbar/navbar"
}
}
页面配置navigationStyle设置为custom的时候可以使用此组件替代原生导航栏,设置后效果
设置完之后内容就是以最顶部为起点
接下来使用自定义组件navbar来实现顶部样式与返回与首页胶囊
自定义组件
首先分析下导航栏布局:
- 顶部状态栏
- 主要内容区
- 胶囊
- title
布局分析完之后,接下来就是代码实现
wxml
<!-- index.wxml -->
<navbar header="{{header}}"></navbar>
<view class="intro">项目内容</view>
<!-- navbar -->
<view style="height:{{statusHeight+navHeight}}px"></view>
<view class='topbar' style="background:{{header.headerbg}}">
<view class='status' style="height:{{statusHeight}}px"></view>
<view class='navbar' style="height:{{navHeight}}px">
<view class='navbar_home' style="background:{{header.capsulebg}};border:{{header.capsuleborder}}">
<text class="iconfont iconback" wx:if="{{header.backCapsule}}" bindtap='backClick'></text>
<text class="iconfont iconhome" wx:if="{{header.homeCapsule}}" bindtap='homeClick'></text>
</view>
<view class='navbar_title' style="height:{{navHeight}}px">
<view style="color:{{header.fontColor}};font-size:{{header.fontSize}}">{{header.title}}</view>
</view>
</view>
</view>
topbar为最外层view,提供动态配置背景颜色
status为最上面的状态栏,不同机型高度不确定,所以这一块高度也是动态的
navbar为整个自定义区域,不同机型也是高度不确定,所以也是使用变量
navbar下面的 navbar_home 展示自定义胶囊;也需要提供背景颜色可定制,胶囊提供两个按钮,一个返回按钮一个主页,图标使用的是iconfont
navbar_title用于展示标题,这里垂直居中展示就行,提供配置颜色与大小
整个导航需要一直固定在最上面,所以使用fixed定位,最上层div用来占位
wxss
.topbar {
position: fixed;
top: 0;
left: 0;
width: 100%;
z-index: 9999;
}
.status {
width: 100%;
}
.navbar {
width: 100%;
display: flex;
justify-content: flex-start;
align-items: center;
text-align: center;
position: relative;
}
.navbar_home {
position: absolute;
left: 32rpx;
display: flex;
justify-content: flex-start;
align-items: center;
border-radius: 33rpx;
border: 1px solid rgba(0, 0, 0, 0.1);
background: rgba(0,0,0,0.2);
box-sizing: border-box;
padding: 10rpx 0;
}
.navbar_home .iconfont {
padding: 0 20rpx;
}
.navbar_home .iconfont:nth-child(2) {
border-left: 1px solid #333;
opacity: 0.7;
}
.navbar_title {
position: absolute;
width: 100%;
display: flex;
justify-content: center;
align-items: center;
z-index: -1;
}
.navbar_title view {
width: 40%;
word-break: break-all;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
font-size: 38rpx;
}
js
逻辑处理:主要是高度计算,与两个按钮的点击事件
高度计算:
通过小程序提供api wx.getSystemInfo来动态获取高度与机型
statusBarHeight 状态栏的高度,单位px
通过res.system来判断ios还是andriod,如果是ios 导航栏为44px,andriod为48px
胶囊事件:
点击主页按钮则直接使用wx.switchTab回到主页
点击返回事件先通过getCurrentPages判断调用栈,如果为空直接回到首页
Component({
properties: {
header: {
type: Object,
value: {
homeCapsule: true, // 是否展示首页
backCapsule: true, // 是否展示返回
headerbg: "#fff", // 背景颜色
title: "", // 标题
fontColor: "#000", // 字体颜色
fontSize: '16', // 标题字体大小
capsulebg: 'rgba(0,0,0,0.2)', // 胶囊样式
capsuleborder: '1px solid rgba(0, 0, 0, 0.1)',
capsulesep: '1px solid rgba(255,255,255,0.2)'
}
}
},
options: {
styleIsolation: 'apply-shared',
},
methods: {
backClick() {
if (getCurrentPages().length == 1) {
this.homeClick()
} else {
wx.navigateBack({
delta: 1
})
}
},
homeClick() {
wx.switchTab({
url: '/pages/homepage/homepage',
})
}
},
attached() {
var self = this;
wx.getSystemInfo({
success(res) {
var isIos = res.system.indexOf('iOS') > -1;
self.setData({
statusHeight: res.statusBarHeight,
navHeight: isIos ? 44 : 48
})
}
})
}
})
完成后效果图
因为navbar组件是通用组件,在app.json配置,最后提供完整的代码片段
总结
- 使用"navigationStyle": "custom"配置项使导航可配置
- 使用自组件在动态配置所需要的功能与样式
- 通过wx.getSystemInfo API来解决兼容问题