一、 最终效果
二、实现了功能
1、nav左侧返回icon支持自定义点击返回事件(默认返回上一步)
2、nav左侧支持既显示返回又显示返回首页icon
3、nav左侧只显示返回icon
4、nav左侧只显示返回首页icon
5、nav左侧自定义left插槽
6、nav中间支持title命名
7、nav中间支持center插槽
8、支持自定义背景颜色:backgroundColor
9、支持修改icon大小、颜色
10、支持导航栏文字颜色自定义
11、支持自定义返回指定页面并可以传参(goBackUrl、urlParam)
12、支持自定义导航栏高度(默认设备高度)
三、navbar参数配置
1、代码示例:
<navbar titleText="登录页面"/>
2、 配置参数(Attributes)
参数 | 说明 | 类型 | 默认值 |
---|---|---|---|
backgroundColor | 导航栏背景颜色 | String | #355db4 |
navCustomHeight | 自定义导航栏高度(单位rpx) | number | 0 |
color | 导航栏文字颜色 | String | #fff |
fontSize | 导航栏文字大小(单位rpx) | number | 32 |
iconSize | 导航栏图标大小 | number | 18 |
iconColor | 导航栏图标颜色 | String | #fff |
titleText | 导航栏标题 | String | - |
backMain | 是否显示返回首页图标 | boolean | false |
isGoBack | 是否显示返回图标 | boolean | false |
isGoBackEvent | 是否自定义写返回事件 | boolean | false |
goBackUrl | 返回指定页面路径 | string | - |
urlParam | 返回指定页面路径参数 | string | - |
3、 Events
事件名 | 说明 | 返回值 |
---|---|---|
goBack | 自定义返回事件 | - |
4、Slot
事件名 | 说明 |
---|---|
left | 左侧具名插槽 |
center | 导航栏标题插槽) |
- | 默认插槽 |
四、源码
<template>
<view class="nav" :style="navStyle">
<view :style="statusBarStyle"></view>
<view class="navBar" :style="navBarStyle">
<view class="nav_bar_left" :style="{ color }">
<!-- 既显示返回又显示返回首页icon -->
<view v-if="isGoBack && backMain" class="back-home">
<view class="back flex-box flex-ver" @tap="goBack">
<uni-icons class="imageClass" :size="iconSize" type="left" :color="iconColor"></uni-icons>
</view>
<view class="line"></view>
<view class="home flex-box flex-ver" @tap="goHome">
<uni-icons class="imageClass" :size="iconSize" type="home" :color="iconColor"></uni-icons>
</view>
</view>
<!-- 只显示返回icon -->
<view v-else-if="isGoBack || pages > 1" class="flex-box flex-ver-v" @click.stop="goBack">
<uni-icons class="imageClass" :size="iconSize" type="left" :color="iconColor"></uni-icons>
</view>
<!-- 只显示返回首页icon -->
<view v-else-if="backMain" class="flex-box flex-ver-v" @click.stop="goHome">
<uni-icons class="imageClass" :size="iconSize" type="home" :color="iconColor"></uni-icons>
</view>
<!-- 自定义插槽 -->
<view v-else class="flex-box flex-ver-v">
<slot name="left" />
</view>
</view>
<view class="nav-title" v-if="titleText">
<view :style="textStyle">{{ titleText }}</view>
</view>
<view class="center" v-else>
<slot name="center" />
</view>
</view>
<slot />
</view>
</template>
<script setup lang="ts">
interface Search {
backgroundColor?: string; // 导航栏背景颜色--可以是渐变
navCustomHeight?: number; // 自定义导航栏高度
color?: string; // 导航栏文字颜色
fontSize?: number; // 导航栏文字大小
iconSize?: number; // 导航栏图标大小
iconColor?: string; // 导航栏图标颜色
titleText?: string; // 导航栏标题
backMain?: boolean; // 是否显示返回首页图标
isGoBack?: boolean; // 是否显示返回图标
isGoBackEvent?: boolean; // 是否自定义写返回事件
goBackUrl?: string; // 返回的url
urlParam?: string; // 返回的url参数
}
const props = withDefaults(defineProps<Search>(), {
backgroundColor: "#355db4",
color: "#fff",
fontSize: 32,
iconSize: 18,
iconColor: "#fff",
navCustomHeight: 0,
titleText: "",
backMain: false,
isGoBack: false,
isGoBackEvent: false,
goBackUrl: "",
urlParam: ""
});
onLoad(() => {
setNavSize();
setStyle();
});
onPageScroll((e: any) => {
// e.scrollTop 表示当前页面滚动的距离
console.log(e);
// 在这里编写你的滚动相关逻辑
});
//状态栏高度
const status = ref(0);
//nav高度
const navHeight = ref(0);
//导航栏高度
const allnavHeight = ref("");
//字体样式
const textStyle = ref("");
// 页面栈的数量
const pages = ref(getCurrentPages().length);
//获取状态栏高度
const setNavSize = () => {
const app = uni.getSystemInfoSync();
const menuButtonInfo = uni.getMenuButtonBoundingClientRect();
let statusBarHeight = app.statusBarHeight || 0;
status.value = statusBarHeight / (uni.upx2px(100) / 100);
navHeight.value = menuButtonInfo.height / (uni.upx2px(100) / 100) + 30;
allnavHeight.value = status.value + navHeight.value + "rpx;";
};
const emits = defineEmits(["goBack"]);
const navStyle = computed(() => ({
height: props.navCustomHeight ? `${props.navCustomHeight}rpx` : allnavHeight.value,
background: props.backgroundColor
}));
const statusBarStyle = computed(() => `height:${status.value}rpx;`);
const navBarStyle = computed(() => `height:${navHeight.value}rpx;max-height:${navHeight.value}rpx;`);
//样式设置
const setStyle = () => {
textStyle.value = ["color:" + props.color, "font-size:" + props.fontSize + "rpx"].join(";");
};
// 返回上一步
const goBack = () => {
console.log("goBackUrl", pages.value);
if (props.goBackUrl != "") {
uni.redirectTo({
url: `${props.goBackUrl}?${props.urlParam}`
});
} else {
if (!props.isGoBackEvent && pages.value > 1) {
uni.navigateBack();
} else {
emits("goBack");
}
}
};
// 返回首页
const goHome = () => {
uni.reLaunch({
url: "/pages/tabbarPage/tabbarPage"
});
};
</script>
<style lang="scss">
.nav {
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 1;
width: 100%;
background-size: cover;
background-repeat: no-repeat;
background-position: top;
.navBar {
position: relative;
display: flex;
align-items: center;
.nav_bar_left {
height: inherit;
position: absolute;
width: 75px;
display: flex;
align-items: center;
margin-left: 10px;
.back-home {
display: flex;
align-items: center;
width: 100%;
background: rgba(255, 255, 255, 0.6);
border-radius: 16px;
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);
}
}
.back-icon {
display: flex;
align-items: center;
width: 32rpx;
height: 100%;
margin-left: 20rpx;
.imageClass {
display: flex;
justify-content: center;
align-items: center;
}
}
}
.nav-title {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.center {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
}
.flex-box {
display: -webkit-box;
display: -webkit-flex;
display: flex;
}
.flex-ver {
align-items: center;
justify-content: center;
}
.flex-ver-v {
align-items: center;
}
}
</style>
相关文章
基于ElementUi再次封装基础组件文档
Vue3+Vite+Ts+Pinia+Qiankun后台管理系统
vue3+ts基于Element-plus再次封装基础组件文档