uniapp开发微信小程序自定义导航栏
uniapp开发微信小程序自定义导航栏
在开发小程序过程中,我们经常会遇到官方提供的导航栏无法满足业务需求的情况,这个时候就需要我们自定义一个顶部导航栏了,在自定义顶部导航的时候我们要考虑对各设备的兼容性,我们都知道,每款机型的状态栏高度都不一定是相等的,还是胶囊的位置,所以在自定义导航栏组件时要充分考虑在各个设备上的兼容性
话不多说直接上代码!!!
<template><view class="navigation-bar" :class="extClass"><view class="navigation-bar__inner" :class="ios ? 'ios' : 'android'":style="{color: color,background: background,...displayStyleObj,...innerPaddingRightObj,...safeAreaTopObj}"><!-- 左侧按钮 --><view class="navigation-bar__left" :style="leftWidthObj"><template v-if="back || homeButton"><!-- 返回上一页 --><view v-if="back" class="navigation-bar__buttons navigation-bar__buttons_goback"><view@click="backHandler"class="navigation-bar__btn_goback_wrapper":hover-class="hoverClass"hover-stay-time="100"aria-role="button"aria-label="返回"><view class="navigation-bar__button navigation-bar__btn_goback"></view><view v-if="showBackText" class="navigation-bar__text">{{ backText }}</view></view></view><!-- 返回首页 --><view v-if="homeButton" class="navigation-bar__buttons navigation-bar__buttons_home"><view@click="homeHandler"class="navigation-bar__btn_home_wrapper":hover-class="hoverClass"aria-role="button"aria-label="首页"><view class="navigation-bar__button navigation-bar__btn_home"></view></view></view></template><template v-else><slot name="left"></slot></template></view><!-- 标题 --><view class="navigation-bar__center"><view v-if="loading" class="navigation-bar__loading" aria-role="alert"><viewclass="loading"aria-role="img"aria-label="加载中"></view></view><template v-if="title"><text>{{ title }}</text></template><template v-else><slot name="center"></slot></template></view><!-- 右侧留空 --><view class="navigation-bar__right"><slot name="right"></slot></view></view></view>
</template><script>
import { ref, reactive, watch, onMounted } from 'vue';export default {name: 'NavigationBar',props: {extClass: {type: String,default: ''},title: {type: String,default: ''},background: {type: String,default: ''},color: {type: String,default: ''},back: {type: Boolean,default: true},loading: {type: Boolean,default: false},homeButton: {type: Boolean,default: false},animated: {type: Boolean,default: true},show: {type: Boolean,default: true},delta: {type: Number,default: 1},showBackText: {type: Boolean,default: false},backText: {type: String,default: '返回'}},emits: ['back', 'home'],setup(props, { emit }) {const ios = ref(false);const innerPaddingRight = ref('');const leftWidth = ref('');const safeAreaTop = ref('');const displayStyle = ref('');const hoverClass = ref('active');const displayStyleObj = reactive({});const innerPaddingRightObj = reactive({});const leftWidthObj = reactive({});const safeAreaTopObj = reactive({});// 显示状态变化处理const showChange = (show) => {if (props.animated) {displayStyleObj.opacity = show ? '1' : '0';displayStyleObj.transition = 'opacity 0.5s';} else {displayStyleObj.display = show ? '' : 'none';}};// 监听 show 属性变化watch(() => props.show, (newVal) => {showChange(newVal);}, { immediate: true });// 返回按钮处理const backHandler = () => {if (props.delta) {uni.navigateBack({delta: props.delta});}emit('back', { delta: props.delta });};// 首页按钮处理const homeHandler = () => {emit('home');// 实际项目中可能需要跳转到首页// uni.switchTab({ url: '/pages/index/index' });};// 初始化导航栏样式const initNavigationBar = () => {try {const rect = uni.getMenuButtonBoundingClientRect();const windowInfo = uni.getWindowInfo();const deviceInfo = uni.getDeviceInfo();const isAndroid = deviceInfo.platform === 'android';const isDevtools = deviceInfo.platform === 'devtools';let safeAreaTopValue = windowInfo.safeArea?.top || windowInfo.statusBarHeight;if (isAndroid) {if ((!windowInfo.safeArea?.top && windowInfo.statusBarHeight > 0) || windowInfo.safeArea?.top === 0) {safeAreaTopValue = windowInfo.statusBarHeight;} else {safeAreaTopValue = 40;}}ios.value = !isAndroid;innerPaddingRightObj.paddingRight = `${windowInfo.windowWidth - rect.left}px`;leftWidthObj.minWidth = `${windowInfo.windowWidth - rect.left}px`;leftWidthObj.maxWidth = `${windowInfo.windowWidth - rect.width}px`;if (isDevtools || isAndroid) {safeAreaTopObj.height = `calc(var(--height) + ${safeAreaTopValue}px)`;safeAreaTopObj.paddingTop = `${safeAreaTopValue}px`;} else {safeAreaTopObj.height = '';safeAreaTopObj.paddingTop = '';}} catch (e) {console.error('NavigationBar init error:', e);}};onMounted(() => {initNavigationBar();});return {ios,innerPaddingRightObj,leftWidthObj,safeAreaTopObj,displayStyleObj,hoverClass,backHandler,homeHandler};}
};
</script><style scoped>
.navigation-bar {/* width: 100%;position: fixed; */--weui-FG-0: rgba(255, 255, 255, 1);--height: 44px;--left: 16px;overflow: hidden;color: var(--weui-FG-0);flex: none;
}.navigation-bar .android {--height: 48px;
}.navigation-bar__inner {position: relative;top: 0;left: 0;height: calc(var(--height) + env(safe-area-inset-top));display: flex;flex-direction: row;align-items: center;justify-content: center;padding-top: env(safe-area-inset-top);width: 100%;box-sizing: border-box;
}.navigation-bar__left {position: relative;padding-left: var(--left);display: flex;flex-direction: row;justify-content: flex-start;align-items: center;height: 100%;box-sizing: border-box;
}.navigation-bar__btn_goback_wrapper {display: flex;align-items: center;padding: 11px 18px 11px 16px;margin: -11px -18px -11px -16px;
}.navigation-bar__btn_goback_wrapper.active {opacity: 0.5;
}.navigation-bar__btn_home_wrapper {display: flex;align-items: center;padding: 11px 18px 11px 16px;margin: -11px -18px -11px -16px;
}.navigation-bar__btn_home_wrapper.active {opacity: 0.5;
}.navigation-bar__btn_home {font-size: 12px;width: 22px;height: 22px;-webkit-mask: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' fill='none' version='1.1' width='20' height='20' viewBox='0 0 20 20'%3E%3Cdefs%3E%3CclipPath id='master_svg0_211_16780'%3E%3Crect x='0' y='0' width='20' height='20' rx='0'/%3E%3C/clipPath%3E%3C/defs%3E%3Cg clip-path='url(%23master_svg0_211_16780)'%3E%3Cg%3E%3Cpath d='M1.914707238786316,9.37944225C1.717148598786316,9.37944225,1.522812618786316,9.28602455,1.401328358786316,9.11163045C1.204023636786316,8.82840725,1.2736720437863158,8.43885615,1.556914358786316,8.24155135L9.643497388786315,2.60825122C9.864889988786317,2.454042371,10.160245788786316,2.459295034,10.376015588786316,2.6212787L17.878693388786317,8.25455955C18.154728388786317,8.46182535,18.210469388786315,8.85360285,18.003224388786315,9.12963865C17.795977388786316,9.40567445,17.404200388786315,9.46143575,17.128145388786315,9.25415035L9.987011788786315,3.8923529500000003L2.271386558786316,9.26721625C2.166818558786316,9.34032395,2.042296948786316,9.379503249999999,1.914707238786316,9.37944225ZM16.235177388786315,18.11829075L11.885059388786315,18.11829075C11.539884388786316,18.11829075,11.260059188786316,17.838465749999997,11.260059188786316,17.49329075L11.260059188786316,13.12463875L8.752305888786317,13.12463875L8.752305888786317,17.49329075C8.752305888786317,17.838465749999997,8.472480688786316,18.11829075,8.127304888786316,18.11829075L3.683379488786316,18.11829075C3.338203288786316,18.11829075,3.058379288786316,17.838465749999997,3.058379288786316,17.49329075L3.058379288786316,10.023114249999999C3.058379288786316,9.67793895,3.338203288786316,9.398114249999999,3.683379488786316,9.398114249999999C4.028554988786317,9.398114249999999,4.308379288786316,9.67793895,4.308379288786316,10.023114249999999L4.308379288786316,16.86829075L7.502304888786316,16.86829075L7.502304888786316,12.49963875C7.502304888786316,12.15446285,7.782129688786316,11.87463855,8.127304888786316,11.87463855L11.885059388786315,11.87463855C12.230234388786316,11.87463855,12.510059388786315,12.15446285,12.510059388786315,12.49963875L12.510059388786315,16.86829075L15.610196388786315,16.86829075L15.610196388786315,10.023114249999999C15.610196388786315,9.67793895,15.890021388786316,9.398114249999999,16.235197388786318,9.398114249999999C16.580369388786316,9.398114249999999,16.860197388786318,9.67793895,16.860197388786318,10.023114249999999L16.860197388786318,17.49329075C16.860177388786315,17.83844675,16.580350388786314,18.11829075,16.235177388786315,18.11829075Z' fill='%23FFFFFF' fill-opacity='1' style='mix-blend-mode:passthrough'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E") no-repeat 50% 50%;mask: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' fill='none' version='1.1' width='20' height='20' viewBox='0 0 20 20'%3E%3Cdefs%3E%3CclipPath id='master_svg0_211_16780'%3E%3Crect x='0' y='0' width='20' height='20' rx='0'/%3E%3C/clipPath%3E%3C/defs%3E%3Cg clip-path='url(%23master_svg0_211_16780)'%3E%3Cg%3E%3Cpath d='M1.914707238786316,9.37944225C1.717148598786316,9.37944225,1.522812618786316,9.28602455,1.401328358786316,9.11163045C1.204023636786316,8.82840725,1.2736720437863158,8.43885615,1.556914358786316,8.24155135L9.643497388786315,2.60825122C9.864889988786317,2.454042371,10.160245788786316,2.459295034,10.376015588786316,2.6212787L17.878693388786317,8.25455955C18.154728388786317,8.46182535,18.210469388786315,8.85360285,18.003224388786315,9.12963865C17.795977388786316,9.40567445,17.404200388786315,9.46143575,17.128145388786315,9.25415035L9.987011788786315,3.8923529500000003L2.271386558786316,9.26721625C2.166818558786316,9.34032395,2.042296948786316,9.379503249999999,1.914707238786316,9.37944225ZM16.235177388786315,18.11829075L11.885059388786315,18.11829075C11.539884388786316,18.11829075,11.260059188786316,17.838465749999997,11.260059188786316,17.49329075L11.260059188786316,13.12463875L8.752305888786317,13.12463875L8.752305888786317,17.49329075C8.752305888786317,17.838465749999997,8.472480688786316,18.11829075,8.127304888786316,18.11829075L3.683379488786316,18.11829075C3.338203288786316,18.11829075,3.058379288786316,17.838465749999997,3.058379288786316,17.49329075L3.058379288786316,10.023114249999999C3.058379288786316,9.67793895,3.338203288786316,9.398114249999999,3.683379488786316,9.398114249999999C4.028554988786317,9.398114249999999,4.308379288786316,9.67793895,4.308379288786316,10.023114249999999L4.308379288786316,16.86829075L7.502304888786316,16.86829075L7.502304888786316,12.49963875C7.502304888786316,12.15446285,7.782129688786316,11.87463855,8.127304888786316,11.87463855L11.885059388786315,11.87463855C12.230234388786316,11.87463855,12.510059388786315,12.15446285,12.510059388786315,12.49963875L12.510059388786315,16.86829075L15.610196388786315,16.86829075L15.610196388786315,10.023114249999999C15.610196388786315,9.67793895,15.890021388786316,9.398114249999999,16.235197388786318,9.398114249999999C16.580369388786316,9.398114249999999,16.860197388786318,9.67793895,16.860197388786318,10.023114249999999L16.860197388786318,17.49329075C16.860177388786315,17.83844675,16.580350388786314,18.11829075,16.235177388786315,18.11829075Z' fill='%23FFFFFF' fill-opacity='1' style='mix-blend-mode:passthrough'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E") no-repeat 50% 50%;-webkit-mask-size: cover;mask-size: cover;background-color: var(--weui-FG-0);
}.navigation-bar__btn_goback {font-size: 12px;width: 17.5px;height: 17.5px;-webkit-mask: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1024 1024' width='100%25' height='100%25'%3E%3Cpath d='M940.8 428.8H282.88l264.96-264.96c32-32 32-84.48 0-117.76s-84.48-32-117.76 0L24.32 453.12c-3.84 3.84-7.68 7.68-10.24 12.8-1.28 2.56-2.56 3.84-3.84 6.4l-3.84 7.68c-1.28 2.56-1.28 5.12-2.56 8.96-1.28 2.56-1.28 5.12-2.56 6.4-2.56 10.24-2.56 21.76 0 32 0 2.56 1.28 5.12 2.56 6.4 1.28 2.56 1.28 5.12 2.56 8.96l3.84 7.68c1.28 2.56 2.56 3.84 3.84 6.4 2.56 5.12 6.4 8.96 10.24 12.8l407.04 407.04c32 32 84.48 32 117.76 0 32-32 32-84.48 0-117.76L282.88 595.2h657.92c46.08 0 83.2-37.12 83.2-83.2s-37.12-83.2-83.2-83.2z' fill='%23ffffff'/%3E%3C/svg%3E") no-repeat 50% 50%;mask: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1024 1024' width='100%25' height='100%25'%3E%3Cpath d='M940.8 428.8H282.88l264.96-264.96c32-32 32-84.48 0-117.76s-84.48-32-117.76 0L24.32 453.12c-3.84 3.84-7.68 7.68-10.24 12.8-1.28 2.56-2.56 3.84-3.84 6.4l-3.84 7.68c-1.28 2.56-1.28 5.12-2.56 8.96-1.28 2.56-1.28 5.12-2.56 6.4-2.56 10.24-2.56 21.76 0 32 0 2.56 1.28 5.12 2.56 6.4 1.28 2.56 1.28 5.12 2.56 8.96l3.84 7.68c1.28 2.56 2.56 3.84 3.84 6.4 2.56 5.12 6.4 8.96 10.24 12.8l407.04 407.04c32 32 84.48 32 117.76 0 32-32 32-84.48 0-117.76L282.88 595.2h657.92c46.08 0 83.2-37.12 83.2-83.2s-37.12-83.2-83.2-83.2z' fill='%23ffffff'/%3E%3C/svg%3E") no-repeat 50% 50%;-webkit-mask-size: cover;mask-size: cover;background-color: var(--weui-FG-0);
}.navigation-bar__text {font-size: 17.5px;margin-left: 10px;font-weight: 600;
}.navigation-bar__center {font-size: 17px;text-align: center;position: relative;display: flex;flex-direction: row;align-items: center;justify-content: center;font-weight: bold;flex: 1;height: 100%;
}.navigation-bar__loading {margin-right: 4px;align-items: center;
}.loading {font-size: 16px;width: 16px;height: 16px;display: block;background: transparent url("data:image/svg+xml,%3C%3Fxml version='1.0' encoding='UTF-8'%3F%3E%3Csvg width='80px' height='80px' viewBox='0 0 80 80' version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'%3E%3Ctitle%3Eloading%3C/title%3E%3Cdefs%3E%3ClinearGradient x1='94.0869141%25' y1='0%25' x2='94.0869141%25' y2='90.559082%25' id='linearGradient-1'%3E%3Cstop stop-color='%23606060' stop-opacity='0' offset='0%25'%3E%3C/stop%3E%3Cstop stop-color='%23606060' stop-opacity='0.3' offset='100%25'%3E%3C/stop%3E%3C/linearGradient%3E%3ClinearGradient x1='100%25' y1='8.67370605%25' x2='100%25' y2='90.6286621%25' id='linearGradient-2'%3E%3Cstop stop-color='%23606060' offset='0%25'%3E%3C/stop%3E%3Cstop stop-color='%23606060' stop-opacity='0.3' offset='100%25'%3E%3C/stop%3E%3C/linearGradient%3E%3C/defs%3E%3Cg stroke='none' stroke-width='1' fill='none' fill-rule='evenodd' opacity='0.9'%3E%3Cg%3E%3Cpath d='M40,0 C62.09139,0 80,17.90861 80,40 C80,62.09139 62.09139,80 40,80 L40,73 C58.2253967,73 73,58.2253967 73,40 C73,21.7746033 58.2253967,7 40,7 L40,0 Z' fill='url(%23linearGradient-1)'%3E%3C/path%3E%3Cpath d='M40,0 L40,7 C21.7746033,7 7,21.7746033 7,40 C7,58.2253967 21.7746033,73 40,73 L40,80 C17.90861,80 0,62.09139 0,40 C0,17.90861 17.90861,0 40,0 Z' fill='url(%23linearGradient-2)'%3E%3C/path%3E%3Ccircle id='Oval' fill='%23606060' cx='40.5' cy='3.5' r='3.5'%3E%3C/circle%3E%3C/g%3E%3C/g%3E%3C/svg%3E%0A") no-repeat;background-size: 100%;margin-left: 0;animation: loading linear infinite 1s;
}@keyframes loading {from {transform: rotate(0);}to {transform: rotate(360deg);}
}
</style>
如果样式icon不符合项目UI的话,后期可以自己进行更改