• uniapp使用vue3语法构建自定义导航栏,适配小程序胶囊


    具体代码

    <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: transparent);
    		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的高度)

    在这里插入图片描述

  • 相关阅读:
    java98-线程join使用中断进行另一个
    flink-sql自定义函数
    1.8、习题1-体系结构相关真题
    Prometheus应用监控
    阿里云ECS11月销量王 99元/年
    vue 计算属性未重新计算 / computed 未触发 / computed 原理&源码分析
    炒冷饭、语雀崩、领会员-我最主观的一段文字
    Azure Arc 概要:功能、管理和应用场景详解,AZ900 考点示例
    神经网络中的偏置(bias)究竟有什么用?
    慕课网前端面试06--js基础-作用域和闭包
  • 原文地址:https://blog.csdn.net/weixin_28717693/article/details/139627469