自定义导航&自定义tabbar
一、自定义导航
1、创建一个自定义导航组件
思路:首先先写一个自己需要的组件,然后再使用的页面的json中注册组件,并且再页面上使用,js里面把配置的data数据配置好。如果是全部使用自定义的就在app.json中配置好,单独页面的话就再单独的页面json里面配置好即可。
在小程序的目录components 下面创建navigation-bar的组件,里面分别包含四个文件。
a. html
<!-- 默认为黑色的返回键-->
<view class='nav-wrap nav-bgc-class' style='height: {{statusBarHeight + navBarHeight}}px;'>
<!-- 左上角的返回按钮 其中wx:if='{{navbarData.showCapsule}}' 是控制左上角按钮的显示隐藏,1为显示,0为隐藏 -->
<view class='nav-capsule' style='margin-top: {{statusBarHeight}}px; height: {{navBarHeight}}px;' wx:if='{{navbarData.showCapsule}}' bindtap='_navback'>
<image class='back-pre ex-back-pre' src='{{navbarData.backSrc || "/img/back4.png"}}' mode='aspectFill'></image>
</view>
<!-- 中间的标题 -->
<view class='nav-title nav-title-class' style='margin-top: {{statusBarHeight}}px; height: {{navBarHeight}}px;'>{{navbarData.title}}</view>
</view>
b.json 文件
{
"component": true
}
c.js
const app = getApp()
Component({
// multipleSlots 为组件开启多插槽模式
options: {
multipleSlots: true,
},
// externalClasses 为组件指定多个外部样式类
externalClasses: ['nav-bgc-class', 'nav-title-class', 'ex-back-pre'],
// properties 组件用来储存外部数据
properties: {
navbarData: { //navbarData 由父页面传递的数据,变量名字自命名
type: Object,
value: {},
observer: function (newVal, oldVal) {}
},
},
// 组件用来储存内部私有数据
data: {
// 自定义导航栏的高度
statusBarHeight: app.globalData.statusBarHeight,
navBarHeight: app.globalData.navBarHeight
},
// attached函数 当组件进入页面节点树时触发,可以使用setData,绝大多数初始化工作在这个时机进行
attached: function () {},
// methods对象 定义组件内的各种方法
methods: {
// 返回键,触发自定义事件,将返回的事件交给父级页面来分情况定义
_navback() {
this.triggerEvent('goBack')
}
}
})
d.wxss
/* 顶部固定定位 标题要居中 自定义按钮和标题要和右边微信原生的胶囊上下对齐 */
.nav-wrap {
position: fixed;
width: 750rpx;
top: 0;
left: 0;
right: 0;
/* background: #f4f4f4; */
background-color: pink;
z-index: 9999999;
transform: translate3d(0, 0, 0);
}
/* 返回键 */
.nav-capsule {
width: 140rpx;
/* 让里面的图片元素垂直居中 */
display: flex;
align-items: center;
}
.back-pre {
width: 100rpx;
height: 68rpx;
}
/* 标题 */
.nav-title {
position: absolute;
left: 0;
right: 0;
bottom: 0;
max-width: 400rpx;
margin: auto;
/* 水平垂直居中 */
display: flex;
align-items: center;
justify-content: space-around;
/* 超出部分省略号显示 */
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
/* 字体设置 */
color: #111111;
font-size: 32rpx;
font-weight: 500;
}
2、页面使用组件
a、页面json注册
{
"usingComponents": {
"nav-bar": "/components/navigation-bar/navigation-bar",
"custom-bar": "/custom-tab-bar/index"
},
"navigationStyle": "custom" //这个地方如果单独一个页面使用就再那个页面配置,如果不是的话可以在全局配置,但是如果全局写了这个值,就都是自定的导航了,这个地方需要注意。
}
b、页面使用
<nav-bar bind:goBack="_goBack" nav-bgc-class="ex-nav-bgc-class" nav-title-class="ex-nav-title-class" ex-back-pre="ex-back-pre" navbar-data='{{nvabarData}}'>
</nav-bar>
c、js配置数据
const app = getApp()
data:{
// 自定义导航栏需要的参数
nvabarData: {
showCapsule: 0, //是否显示左上角图标 1表示显示 0表示不显示
title: '个人中心', //导航栏 中间的标题
backSrc: '/static/image/sy-mr1.png',// 返回键的样式
background:null //这个地方透明就给null,其他颜色直接写背景颜色就好
},
// 此页面 页面内容距最顶部的距离
height: app.globalData.statusBarHeight + app.globalData.navBarHeight,
}
3、全局配置
这里需要注意一个点,就是全局的app.js也需要获取用户的手机高度,不然返回按钮没办法和胶囊对齐。
onLaunch() {
var _this = this;
//自定义导航栏 获取设备顶部窗口的高度(不同设备窗口高度不一样,根据这个来设置自定义导航栏的高度)
wx.getSystemInfo({
success: (res) => {
// 基础库 2.1.0 开始支持wx.getMenuButtonBoundingClientRect(),低版本需要适配
let custom = wx.getMenuButtonBoundingClientRect()
// console.log('状态栏高度',res.statusBarHeight)
// console.log('右上角胶囊按钮的高度', custom.height)
// console.log('右上角胶囊按钮的上边界坐标', custom.top)
// console.log('右上角胶囊按钮的下边界坐标', custom.bottom)
_this.globalData.statusBarHeight = res.statusBarHeight
_this.globalData.navBarHeight = custom.height + (custom.top - res.statusBarHeight) * 2
}
})
},
二、自定义tabbar
1、创建组件
此处要注意的是,组件创建的位置要和最外层平级,要不不显示,我自己遇到的问题是这样的。
也是一样的依次是四个文件分别都写一下。或者官网拉个例子抄一下也行。
a、html
<!--miniprogram/custom-tab-bar/index.wxml-->
<cover-view class="tab-bar">
<cover-view class="tab-bar-border"></cover-view>
<cover-view wx:for="{{list}}" wx:key="index" class="tab-bar-item" data-path="{{item.pagePath}}" data-index="{{index}}" bindtap="switchTab">
<cover-image src="{{selected === index ? item.selectedIconPath : item.iconPath}}"></cover-image>
<cover-view style="color: {{selected === index ? selectedColor : color}}">{{item.text}}</cover-view>
</cover-view>
</cover-view>
b、js
var app = getApp();
Component({
properties: {},
data: {
selected: 0,
color: "#7A7E83", // 颜色
selectedColor: "#FF0000", // 被选中颜色
list: [{
pagePath: "/pages/index/index",
text: "首页",
iconPath: "/static/image/sy-mr1.png",
selectedIconPath: "/static/image/sy-xz1.png"
}, {
pagePath: "/pages/firstTest/index",
text: "我的",
iconPath: "/static/image/wd-mr2.png",
selectedIconPath: "/static/image/wd-xz2.png"
}],
},
pageLifetimes: {
// 组件所在页面的生命周期函数
show: () => {},
hide: () => {}
},
lifetimes: {
attached: function () {
// 在组件实例进入页面节点树时执行
},
detached: function () {
// 在组件实例被从页面节点树移除时执行
},
},
methods: {
switchTab(e) {
var url = e.currentTarget.dataset.path
const data = e.currentTarget.dataset
wx.switchTab({
url
})
this.setData({
selected: data.index
})
}
}
})
c、json
{
"component": true
}
d、wxss
.tab-bar {
position: fixed;
bottom: 0;
left: 0;
right: 0;
height: 48px;
background: white;
display: flex;
padding-bottom: env(safe-area-inset-bottom);
}
.tab-bar-border {
background-color: rgba(0, 0, 0, 0.33);
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 1px;
transform: scaleY(0.5);
}
.tab-bar-item {
flex: 1;
text-align: center;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
.tab-bar-item cover-image {
width: 27px;
height: 27px;
}
.tab-bar-item cover-view {
font-size: 10px;
}
2、在使用的页面引入
json引入即可不用再页面上写组件。
{
"usingComponents": {
"custom-bar": "/custom-tab-bar/index"
}
}
最主要的是在js把页面对应上自己的index即可
onShow() {
if (typeof this.getTabBar === 'function' &&
this.getTabBar()) {
this.getTabBar().setData({
selected: 0
})
}
},