// 第一种
<div class="place-holder" :style="{ height: menuSettings.navBarHeight + 'px'}">div>
<nav-bar title="司机首页" />
// 第二种
<div class="place-holder" :style="{ height: menuSettings.navBarHeight + 'px'}">div>
<nav-bar title="自助排队" :isGoBack="true" :isGoBackEvent="true" />
// 第三种
<div class="place-holder" :style="{ height: menuSettings.navBarHeight + 'px'}">div>
<nav-bar title="我的任务" :showSearch="true" @search="search" />
// 第四种
<div class="place-holder" :style="{ height: menuSettings.navBarHeight + 'px'}">div>
<nav-bar title="自助排队" :isGoBack="true" :backMain="true" :isGoBackEvent="true" />
注释:
isGoBack:表是否显示返回icon
isGoBackEvent:表点击返回后是否需要判断确定离开当前页面(作用于新增页面离开时是否需要提示用户当前数据未保存,是否确定离开);紧随@goBack事件
backMain:表是否显示返回主页icon
showSearch:表是否显示搜索icon
分为三步思路:
1.确定自定义导航栏高度
2.确定右侧囊体宽高以确定自定义左侧囊体
3.具体细节
新建一个systemSetting.js文件,代码如下
const statusBar = {
android: 24,
iPhone: 20,
newModel: 44, // 长屏下默认高度
};
const navigationBar = {
default: 44,
};
const navBarStyle = {
background: "",
color: "",
textAlignAndroid: "left",
textAlignIPhone: "center",
textAlign: "center",
fontSize: 18,
};
export { statusBar, navigationBar, navBarStyle };
根据wx.getMenuButtonBoundingClientRect()接口的返回值包括了囊体的宽高,在组件代码中即可调用来取得
a.根据前面获取到的导航栏高和囊体大小,将这些值存入vuex以后续调用
b.在模板处定义对应的不同场景--有home及back或search或单独的back囊体或无该左侧囊体;在js的判断中根据具体条件场景去进一步判断是否需要显示哪一种左侧囊体。
c.在各自对应的需要加入导航栏的页面引入该组件,因为原导航栏占位不再且自定义导航栏position被设置为fixed,故记得在使用的页面对应引入高度占位。如下place-holder的div
<template>
<div class="navigation-bar flex-box flex-ver-v" @click.stop="full" :style="navigationBarStyle">
<div v-if="showSearch" :style="searchStyle" class="search-home">
<van-icon @click.stop="searchShow" v-if="!show" name="search" color="#fff" size="20px" />
<div class="seach-content" v-if="show">
<van-search
:value="accountInput"
placeholder="请输入搜索关键词"
use-action-slot
show-action
focus
@change="onChange"
>
<view slot="action" @click.stop="onClick">搜索view>
van-search>
div>
div>
<div v-else class="back-margin-left" :style="searchStyle">
<div v-if="isGoBack&&backMain" class="back-home">
<div
class="back flex-box flex-ver"
@click.stop="goBack"
v-if="isGoBack"
:style="{height: menuSettings.height + 'px'}"
>
<van-icon name="arrow-left" />
div>
<div class="line">div>
<div
class="home flex-box flex-ver"
@click="goHome"
v-if="backMain"
:style="{height: menuSettings.height + 'px'}"
>
<van-icon name="wap-home-o" />
div>
div>
<div v-else>
<div
class="flex-box flex-ver-v"
@click.stop="goBack"
v-if="isGoBack"
:style="{height: menuSettings.height + 'px'}"
>
<van-icon name="arrow-left" color="#fff" size="20px" />
div>
div>
div>
<div v-if="!show" class="title" :style="titleStyle">{{title}}div>
<div class="back-margin-right" :style="rightStyle">div>
<div
v-if="show"
:class="[show ?'fullopacity':'']"
:style="{top: height + 'px'}"
@click.stop="full"
>div>
div>
template>
<script>
import { statusBar, navigationBar, navBarStyle } from '@/utils/systemSetting'
import variables from '@/static/styles/variables.scss'
export default {
name: 'NavBar',
props: {
title: {
type: String,
default: ''
},
// title字体颜色
color: {
type: String,
default: `${variables.mainWhite}`
},
// navBar背景颜色
background: {
type: String,
default: `${variables.mainBg}`
},
// 是否显示搜索icon
showSearch: {
type: Boolean,
default: false
},
// 是否显示返回首页icon
backMain: {
type: Boolean,
default: false
},
// 是否返回上一层
isGoBack: {
type: Boolean,
default: false
},
// 返回上一层触发方法
isGoBackEvent: {
type: Boolean,
default: false
}
},
/**
* 组件的初始数据
*/
data () {
return {
paddingTop: statusBar.android, // 默认为android大部分普通机型高度
height: navigationBar.default + statusBar.android,
barStyle: {},
accountInput: '', // 搜索内容
marginTop: 0,
scale: 1,
show: false,
showBackIconLength: 1
}
},
computed: {
menuSettings () {
return this.$store.state.common.menuSettings
},
userType () {
return this.$store.state.user.userType
},
// navBar样式
navigationBarStyle () {
let background = this.background || this.barStyle.background || ''
return `padding-top:${this.paddingTop}px;height:${this.height}px;background:${background};`
},
// 左侧搜索icon或显示返回上一步及显示返回首页样式
searchStyle () {
return `min-width:${this.menuSettings.width}px;height: ${this.menuSettings.height}px;transform:scale(${this.scale})`
},
// nav标题样式
titleStyle () {
let color = this.color || this.barStyle.color
return `text-align:${this.barStyle.textAlign};color: ${color};font-size:${this.barStyle.fontSize}px;line-height:${this.barStyle.height}px`
},
// 右侧胶囊样式
rightStyle () {
return `min-width:${this.menuSettings.width}px;height: ${this.menuSettings.height}px;`
}
},
mounted () {
// 获取系统信息
const systemInfo = wx.getSystemInfoSync()
const ratio = systemInfo.screenHeight / systemInfo.screenWidth // 高宽比例
const isNewModel = ratio >= 2
const isIPhone = systemInfo.model.indexOf('iPhone') >= 0
const barHeight = systemInfo.statusBarHeight || (isNewModel ? statusBar.newModel : isIPhone ? statusBar.iPhone : statusBar.android)
this.paddingTop = barHeight
this.height = barHeight + navigationBar.default
let barStyle = { ...navBarStyle }
barStyle.height = navigationBar.default
this.barStyle = barStyle
this.getMenuSettings(1, 3)
this.scale = 1 - (0.5 / this.menuSettings.height)
this.marginTop = this.menuSettings.top - systemInfo.statusBarHeight + 4
},
/**
* 组件的方法列表
*/
methods: {
// vuex存储menuSettings
getMenuSettings (current, count) {
// 获取胶囊信息
let menuSettings = wx.getMenuButtonBoundingClientRect()
// console.log('menuSettings', menuSettings)
if (!menuSettings.height || menuSettings.height === 0) {
if (current > 3) {
return
}
setTimeout(() => {
this.getMenuSettings(current + 1, count)
}, 200)
} else {
menuSettings.navBarHeight = this.height
this.$store.commit('common/SET_MENU_SETTINGS', menuSettings)
}
},
// 点击搜索icon,显示输入框
searchShow () {
this.show = true
this.accountInput = ''
},
// 输入的内容赋值
onChange (e) {
this.accountInput = e.mp.detail
},
// 点击搜索按钮,并将值传出
onClick () {
this.$emit('search', this.accountInput)
setTimeout(() => {
this.show = false
}, 500)
},
// 隐藏搜索框
full () {
// console.log(111, this.menuSettings)
this.show = false
},
// 返回首页
goHome () {
// 供应商端
if (this.userType === '0') {
wx.reLaunch({
url: '/pages/supplierTask/main'
})
}
// 司机端
if (this.userType === '1') {
wx.reLaunch({
url: '/pages/driverIndex/main'
})
}
},
// 返回上一层
goBack () {
const pages = getCurrentPages()
this.$emit('goBack')
if (this.isGoBack && this.isGoBackEvent && pages.length > 1) {
wx.navigateBack({
delta: 1
})
}
}
}
}
script>
<style lang="scss" scoped>
.navigation-bar {
width: 100vw;
height: 60px;
display: flex;
justify-content: space-between;
position: fixed;
top: 0;
left: 0;
box-sizing: border-box;
z-index: 1000;
}
.flex-box{ display:-webkit-box;display:-webkit-flex;display: flex;}
.flex-ver{align-items:center;justify-content: center;}
.flex-ver-v{align-items:center;}
.search-home {
display: flex;
align-items: center;
padding-left: 10px;
box-sizing: border-box;
overflow: hidden;
.back {
flex: 1;
}
}
.back-margin-right {
margin-right: 10px;
}
.back-home {
display: flex;
align-items: center;
background: rgba(255, 255, 255, 0.6);
border-radius: 16px;
margin-left: 10px;
box-sizing: border-box;
box-shadow: 0 0 1px rgb(207, 207, 207);
overflow: hidden;
.back {
flex: 1;
}
.home {
flex: 1;
}
.line {
width: 1px;
height: 20px;
background: rgba(0, 0, 0, 0.2);
transform: scaleX(0.5);
}
}
.title {
flex: 1;
font-size: 16px;
box-sizing: border-box;
padding: 0 2px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.fullopacity {
position: fixed;
left: 0;
z-index: 1;
width: 100%;
height: 100%;
background: rgb(1, 1, 1);
transition: all 2s;
opacity: 0.5;
}
style>
每个页面使用NavBar组件的上面都要加如下这句代码来占位
<div class="place-holder" :style="{ height: menuSettings.navBarHeight + 'px'}">div>