小程序导航栏设计组件custom-navbar封装
This commit is contained in:
parent
5b555ddf90
commit
aa5e70d5f6
98
components/custom-navbar/README.md
Normal file
98
components/custom-navbar/README.md
Normal file
|
|
@ -0,0 +1,98 @@
|
||||||
|
# CustomNavbar 自定义导航栏组件
|
||||||
|
|
||||||
|
## 功能特性
|
||||||
|
|
||||||
|
- 自动适配微信小程序状态栏高度
|
||||||
|
- 自动计算胶囊按钮高度,确保文字与胶囊水平对齐
|
||||||
|
- 支持自定义标题、返回按钮图标
|
||||||
|
- 支持右侧插槽,可添加自定义内容
|
||||||
|
- 支持返回事件回调
|
||||||
|
|
||||||
|
## 使用方法
|
||||||
|
|
||||||
|
### 基础用法
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<template>
|
||||||
|
<view class="page">
|
||||||
|
<custom-navbar title="页面标题" @back="onBack" />
|
||||||
|
<!-- 页面内容,无需设置 margin-top -->
|
||||||
|
<view class="content">
|
||||||
|
<text>页面内容</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import CustomNavbar from "@/components/custom-navbar/custom-navbar.vue";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
CustomNavbar
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onBack() {
|
||||||
|
console.log('返回按钮被点击');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
|
### 自定义返回按钮图标
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<custom-navbar
|
||||||
|
title="页面标题"
|
||||||
|
:backIcon="customBackIcon"
|
||||||
|
@back="onBack"
|
||||||
|
/>
|
||||||
|
```
|
||||||
|
|
||||||
|
### 隐藏返回按钮
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<custom-navbar
|
||||||
|
title="页面标题"
|
||||||
|
:showBack="false"
|
||||||
|
/>
|
||||||
|
```
|
||||||
|
|
||||||
|
### 添加右侧内容
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<custom-navbar title="页面标题" @back="onBack">
|
||||||
|
<template #right>
|
||||||
|
<view class="right-content">
|
||||||
|
<text>右侧内容</text>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
</custom-navbar>
|
||||||
|
```
|
||||||
|
|
||||||
|
## Props
|
||||||
|
|
||||||
|
| 参数 | 类型 | 默认值 | 说明 |
|
||||||
|
|------|------|--------|------|
|
||||||
|
| title | String | '' | 导航栏标题 |
|
||||||
|
| backIcon | String | CommonEnum.BACK_BUTTON | 返回按钮图标路径 |
|
||||||
|
| showBack | Boolean | true | 是否显示返回按钮 |
|
||||||
|
|
||||||
|
## Events
|
||||||
|
|
||||||
|
| 事件名 | 说明 | 回调参数 |
|
||||||
|
|--------|------|----------|
|
||||||
|
| back | 点击返回按钮时触发 | - |
|
||||||
|
|
||||||
|
## Slots
|
||||||
|
|
||||||
|
| 插槽名 | 说明 |
|
||||||
|
|--------|------|
|
||||||
|
| right | 右侧内容插槽 |
|
||||||
|
|
||||||
|
## 注意事项
|
||||||
|
|
||||||
|
1. 组件会自动计算状态栏和胶囊高度,无需手动设置
|
||||||
|
2. 组件使用 `position: fixed` 定位,确保在页面顶部
|
||||||
|
3. 组件内部包含填充区,页面内容无需设置 `margin-top`
|
||||||
|
4. 组件样式使用 `scoped`,不会影响其他组件
|
||||||
130
components/custom-navbar/custom-navbar.vue
Normal file
130
components/custom-navbar/custom-navbar.vue
Normal file
|
|
@ -0,0 +1,130 @@
|
||||||
|
<template>
|
||||||
|
<view>
|
||||||
|
<!-- 填充区,避免内容被导航栏遮挡 -->
|
||||||
|
<view class="navbar-placeholder" :style="{ height: navBarHeight + 'px' }"></view>
|
||||||
|
|
||||||
|
<!-- 自定义导航栏 -->
|
||||||
|
<view class="custom-navbar" :style="{ paddingTop: statusBarHeight + 'px', height: navBarHeight + 'px' }">
|
||||||
|
<view class="navbar-left" @click="handleBack" :style="{ height: capsuleHeight + 'px', lineHeight: capsuleHeight + 'px' }">
|
||||||
|
<image :src="backIcon" mode="aspectFit" class="back-icon"></image>
|
||||||
|
</view>
|
||||||
|
<view class="navbar-title" :style="{ height: capsuleHeight + 'px', lineHeight: capsuleHeight + 'px' }">{{ title }}</view>
|
||||||
|
<view class="navbar-right" :style="{ height: capsuleHeight + 'px', lineHeight: capsuleHeight + 'px' }">
|
||||||
|
<slot name="right"></slot>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import CommonEnum from "../../enum/common";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'CustomNavbar',
|
||||||
|
props: {
|
||||||
|
title: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
backIcon: {
|
||||||
|
type: String,
|
||||||
|
default: CommonEnum.BACK_BUTTON
|
||||||
|
},
|
||||||
|
showBack: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
statusBarHeight: 0,
|
||||||
|
navBarHeight: 0,
|
||||||
|
menuButtonInfo: null,
|
||||||
|
capsuleHeight: 0,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.getSystemInfo();
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
getSystemInfo() {
|
||||||
|
// 获取系统信息
|
||||||
|
const systemInfo = uni.getSystemInfoSync();
|
||||||
|
// 获取状态栏高度
|
||||||
|
this.statusBarHeight = systemInfo.statusBarHeight;
|
||||||
|
|
||||||
|
// 获取胶囊按钮信息
|
||||||
|
this.menuButtonInfo = uni.getMenuButtonBoundingClientRect();
|
||||||
|
|
||||||
|
// 计算胶囊高度
|
||||||
|
this.capsuleHeight = this.menuButtonInfo.height;
|
||||||
|
|
||||||
|
// 计算导航栏高度(胶囊底部到状态栏顶部的距离)
|
||||||
|
this.navBarHeight = this.menuButtonInfo.bottom + 8;
|
||||||
|
},
|
||||||
|
handleBack() {
|
||||||
|
if (this.showBack) {
|
||||||
|
this.$emit('back');
|
||||||
|
uni.navigateBack({
|
||||||
|
delta: 1
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
/* 填充区样式 */
|
||||||
|
.navbar-placeholder {
|
||||||
|
width: 100%;
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 自定义导航栏样式 */
|
||||||
|
.custom-navbar {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
z-index: 999;
|
||||||
|
padding-top: 0;
|
||||||
|
background-color: #F5F0E7;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding-left: 30rpx;
|
||||||
|
padding-right: 30rpx;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navbar-left {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 60rpx;
|
||||||
|
|
||||||
|
.back-icon {
|
||||||
|
width: 56rpx;
|
||||||
|
height: 56rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.navbar-title {
|
||||||
|
font-size: 36rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #695347;
|
||||||
|
flex: 1;
|
||||||
|
text-align: center;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navbar-right {
|
||||||
|
width: 60rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -1,15 +1,12 @@
|
||||||
<template>
|
<template>
|
||||||
<view class="page">
|
<view class="page">
|
||||||
<!-- 自定义导航栏 -->
|
<!-- 自定义导航栏 -->
|
||||||
<view class="custom-navbar" :style="{ paddingTop: statusBarHeight + 'px', height: navBarHeight + 'px' }">
|
<custom-navbar
|
||||||
<view class="navbar-left" @click="goBack" :style="{ height: capsuleHeight + 'px', lineHeight: capsuleHeight + 'px' }">
|
title="走进平山"
|
||||||
<image :src="CommonEnum.BACK_BUTTON" mode="aspectFit" class="back-icon"></image>
|
@back="onBack"
|
||||||
</view>
|
/>
|
||||||
<view class="navbar-title" :style="{ height: capsuleHeight + 'px', lineHeight: capsuleHeight + 'px' }">走进平山</view>
|
|
||||||
<view class="navbar-right" :style="{ height: capsuleHeight + 'px', lineHeight: capsuleHeight + 'px' }"></view>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<view class="header" :style="{ marginTop: navBarHeight + 'px' }">
|
<view class="header">
|
||||||
<!-- <image src="" mode=""></image> -->
|
<!-- <image src="" mode=""></image> -->
|
||||||
<view>111222</view>
|
<view>111222</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
@ -17,48 +14,23 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import CommonEnum from "../../enum/common";
|
import CustomNavbar from "../../components/custom-navbar/custom-navbar.vue";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
computed: {
|
components: {
|
||||||
CommonEnum() {
|
CustomNavbar
|
||||||
return CommonEnum
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
bgc: {
|
bgc: {
|
||||||
backgroundColor: "#F5F0E7",
|
backgroundColor: "#F5F0E7",
|
||||||
},
|
},
|
||||||
statusBarHeight: 0,
|
|
||||||
navBarHeight: 0,
|
|
||||||
menuButtonInfo: null,
|
|
||||||
capsuleHeight: 0,
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onLoad() {
|
|
||||||
this.getSystemInfo();
|
|
||||||
},
|
|
||||||
methods: {
|
methods: {
|
||||||
goBack() {
|
onBack() {
|
||||||
uni.navigateBack({
|
// 可以在这里添加返回前的逻辑
|
||||||
delta: 1
|
console.log('返回按钮被点击');
|
||||||
});
|
|
||||||
},
|
|
||||||
getSystemInfo() {
|
|
||||||
// 获取系统信息
|
|
||||||
const systemInfo = uni.getSystemInfoSync();
|
|
||||||
// 获取状态栏高度
|
|
||||||
this.statusBarHeight = systemInfo.statusBarHeight;
|
|
||||||
|
|
||||||
// 获取胶囊按钮信息
|
|
||||||
this.menuButtonInfo = uni.getMenuButtonBoundingClientRect();
|
|
||||||
|
|
||||||
// 计算胶囊高度
|
|
||||||
this.capsuleHeight = this.menuButtonInfo.height;
|
|
||||||
|
|
||||||
// 计算导航栏高度(胶囊底部到状态栏顶部的距离)
|
|
||||||
this.navBarHeight = this.menuButtonInfo.bottom + 8;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -72,52 +44,7 @@ page {
|
||||||
border-radius: 0rpx 0rpx 0rpx 0rpx;
|
border-radius: 0rpx 0rpx 0rpx 0rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 自定义导航栏样式 */
|
|
||||||
.custom-navbar {
|
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
z-index: 999;
|
|
||||||
padding-top: 0;
|
|
||||||
background-color: #F5F0E7;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-between;
|
|
||||||
padding-left: 30rpx;
|
|
||||||
padding-right: 30rpx;
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
|
||||||
|
|
||||||
.navbar-left {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
width: 60rpx;
|
|
||||||
|
|
||||||
.back-icon {
|
|
||||||
width: 56rpx;
|
|
||||||
height: 56rpx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.navbar-title {
|
|
||||||
font-size: 36rpx;
|
|
||||||
font-weight: bold;
|
|
||||||
color: #695347;
|
|
||||||
flex: 1;
|
|
||||||
text-align: center;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.navbar-right {
|
|
||||||
width: 60rpx;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.header {
|
.header {
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user