具体代码
<template>
<view class="nav-wrapper-container" :style="'height:'+navBarHeight +'px'">
<view class="nav-status-container" :style="'height:'+navstatusBarHeight +'px;'" />
<view v-if="isCustom" class="nav-content-container" :style="'height:'+navContentHeight +'px;'">
<slot name="left">
</slot>
<slot name="middle"> </slot>
<view :style="'width:'+navPaddingRight+'px;'+'height:40px'"></view>
</view>
<view v-else class="nav-content-container" :style="'height:'+navContentHeight +'px;'">
<image v-if="!isInTab" class="nav-content-left" src="../../static/back.png" mode="widthFix"
@click="handleClickBack" />
<view class="nav-content-middle">
<text>{{titleText}}</text>
</view>
</view>
<slot name="bottom" :style="'height:'+bottomComponentHeight +'px;'"></slot>
</view>
</template>
<script setup>
import {
onBeforeMount,
ref,
defineProps,
defineEmits
} from 'vue'
const emits = defineEmits(['init-height'])
/**
* 整个导航栏的高度
*/
const navBarHeight = ref(0)
/**
* 状态栏高度
*/
const navstatusBarHeight = ref(0)
/**
* 内容高度
*/
const navContentHeight = ref(0)
/**
* 距离右侧胶囊的padding-right
*/
const navPaddingRight = ref(0)
/**
* 是否在tab页
*/
const isInTab = getCurrentPages().length == 1
/**
* 获取导航栏尺寸
*/
const initNavSize = () => {
///获取系统信息
const {
statusBarHeight,
uniPlatform
} = uni.getSystemInfoSync()
///是否支持这个方法
const isNoSupportGetMenuButton = (uniPlatform == "app") || (uniPlatform == "web") || (uniPlatform == "mp-lark")
///内容高度
let contentHeight = 0
///计算内容高度
if (!isNoSupportGetMenuButton) {
///拿到胶囊信息
const menuButton = uni.getMenuButtonBoundingClientRect()
contentHeight = (menuButton.top - statusBarHeight) * 2 + menuButton.height
navPaddingRight.value = menuButton.width + 24
} else {
contentHeight = 48
navPaddingRight.value = 24
}
///赋值状态栏高度
navstatusBarHeight.value = statusBarHeight
///赋值内容高度
navContentHeight.value = contentHeight
///总的高度=内容高度+状态栏高度+bottom组件高度
console.log("props.bottomComponentHeight is " + props.bottomComponentHeight)
console.log("statusBarHeight is " + statusBarHeight)
console.log("contentHeight is " + contentHeight)
navBarHeight.value = statusBarHeight + contentHeight + parseInt(props.bottomComponentHeight)
emits('init-height', navBarHeight.value)
}
/**
* 返回
*/
const handleClickBack = () => {
uni.navigateBack({
delta: 1 // 返回的页面数,这里设置为1表示返回上一页
});
}
const props =
defineProps({
///标题
titleText: {
type: String,
default: ""
},
///是否使用自定义插槽
isCustom: {
type: Boolean,
default: false
},
///bottom组件高度
bottomComponentHeight: {
type: String,
default: "0"
}
})
onBeforeMount(() => {
initNavSize()
})
</script>
<style lang="less">
.nav-wrapper-container {
height: var(--status-bar-height);
width: 100%;
position: fixed;
width: 100%;
top: 0;
background-color: #f3f3f3;
left: 0;
z-index: 2;
align-items: center;
}
.nav-status-container {
width: 100%
}
.nav-content-container {
width: 100%;
display: flex;
position: relative;
align-items: center;
}
.nav-content-left {
width: 40rpx;
margin-left: 12rpx;
}
.nav-content-middle {
position: absolute;
left: 50%;
transform: translate(-50%);
}
</style>
使用方法:
使用默认配置:
<navbar titleText="这是标题"></navbar>
使用自定义插槽:
<navbar :isCustom="true" @init-height="initNavHeight" data-eventsync="true" bottomComponentHeight="45">
<template v-slot:left>
<image class="nav-content-left" src="../../static/back.png" mode="widthFix" @click="handleClickBack" />
</template>
<template v-slot:middle>
<view class="search-bar-middle" @click="handlerClickSearch()">
<image src="../../static/search.png" mode="widthFix" style="width: 24rpx"></image>
<text class="search-bar-middle-text">搜索内容、体系、文章</text>
</view>
</template>
<template v-slot:bottom>
<classify-menu-bar :tabArr="tabArr" @on-change-tab="onChangeTab" class="classify-top-container"></classify-menu-bar>
</template>
</navbar>
一共有三个插槽:
- left: 左侧
- middle:居中
- bottom:固定底部 (需用传递属性,作为底部buttom的高度)