uniapp 自定义导航栏

支持搜索(支持假样子和真输入两种模式)、支持返回,拿走不谢!

先看效果

 

需要在app.vue中动态获取设备信息,主要是将设备参数计算好,存储在globalData中便于组件直接获取

methods:{
    initBounding() {
        const {windowWidth, windowHeight, statusBarHeight}  = uni.getSystemInfoSync()
				
				let menuGap = 7
				let menuWidth = 0
				let menuHeight = 32
				let statusHeight = 7
				
				// #ifdef MP
				const {top, left, right, width, height} = uni.getMenuButtonBoundingClientRect()
				menuGap = windowWidth - right
				menuWidth = width
				menuHeight = height
				statusHeight = top - menuGap
				// #endif

				// #ifdef APP-PLUS
				statusHeight = statusBarHeight
				// #endif
				
				this.globalData.windowWidth = windowWidth
				this.globalData.windowHeight = windowHeight
				this.globalData.statusHeight = statusHeight
				this.globalData.menuGap = menuGap
				this.globalData.menuWidth = menuWidth
				this.globalData.menuHeight = menuHeight

				console.log('=============>>>initBounding', this.globalData)
	}

} 

在components中定义组件:nav-bar

<template>
	<view class="view-wrap">
		<view :style="{height: barHeight}"></view>
		<view class="nav-bar-wrap" :style="{background: background}">
			<view class="status-bar" :style="{height: statusHeight}"></view>
			<view class="nav-bar" :style="{padding: menuGap, gap: menuGap, height: menuHeight}">
				<view class="left" v-if="back" @click="handleBack">
					<uni-icons type="arrowleft" size="26" :color="backColor"></uni-icons>
				</view>
				<view class="search-bar"
					:style="{height: menuHeight, borderRadius: borderRadius, background: searchBackground}"
					@click="handleSearch('to')" v-if="search">
					<icon class="icon" type="search" size="14" :color="iconColor" @click.stop="handleSearch('search')"></icon>
					<input type="text" :placeholder="placeholder" :placeholder-style="placeholderStyle"
						:style="{color: searchColor}" :disabled="disabled" v-model="keyWord" @confirm="handleSearch">
					<icon class="icon" type="clear" size="14" :color="iconColor" v-show="keyWord"
						@click.stop="handleSearch('clear')"></icon>
				</view>
				<view class="container" v-else>
					<slot></slot>
				</view>
				<view class="right" :style="{width: menuWidth, height: menuHeight}"></view>
			</view>
		</view>
	</view>
	
</template>

<script>
	const {
		windowWidth,
		statusHeight,
		menuGap,
		menuWidth,
		menuHeight
	} = getApp().globalData
	export default {
		props: {
			background: {
				type: String,
				default: 'none'
			},
			back: {
				type: Boolean
			},
			backColor: {
				type: String,
				default: '#000'
			},
			search: {
				type: Boolean
			},
			searchValue:{
				type: String,
				default: ''
			},
			disabled: {
				type: Boolean
			},
			searchBackground: {
				type: String,
				default: '#fff'
			},
			iconColor: {
				type: String,
				default: '#999'
			},
			searchColor: {
				type: String,
				default: '#000'
			},
			placeholder: {
				type: String,
				default: '关键字快速搜索'
			},
			placeholderStyle: {
				type: String,
				default: 'color: #999;'
			},
		},
		data() {
			return {
				barHeight:'32px',
				menuGap: '7px',
				menuWidth: '0px',
				menuHeight: '32px',
				statusHeight: '7px',
				borderRadius: '4px',
				keyWord:'',
			};
		},
		watch:{
			searchValue(val){
				this.keyWord = val
			}
		},
		created() {
			this.statusHeight = statusHeight + 'px'
			this.menuGap = menuGap + 'px'
			this.menuWidth = menuWidth + 'px'
			this.menuHeight = menuHeight + 'px'
			this.borderRadius = menuHeight / 2 + 'px'
			this.barHeight = statusHeight + menuHeight + menuGap * 2 + 'px'
		},
		computed: {
			barWidth() {
				if (this.back) {
					return windowWidth - menuWidth - menuGap * 4 - 26 + 'px'
				} else {
					return windowWidth - menuWidth - menuGap * 3 + 'px'
				}
			}
		},
		methods: {
			//处理返回
			handleBack() {
				this.$tools.navTo(-1)
				this.$emit('back')
			},
			//处理搜索
			handleSearch(event) {
				if (event == 'to') {
					this.disabled && this.$emit('search')
				} else if (event == 'search') {
					this.$emit('search', this.keyWord)
				} else if (event == 'clear') {
					this.keyWord = ''
					this.$emit('search', this.keyWord)
				} else if (typeof event == 'object') {
					this.keyWord = event.detail.value.trim()
					this.$emit('search', this.keyWord)
				}
			}
		}
	}
</script>

<style lang="scss" scoped>
	.view-wrap{
		position: relative;
	}
	.nav-bar-wrap {
		position: fixed;
		top: 0;
		z-index: 99;
		width: 750rpx;
		.nav-bar {
			display: flex;
			justify-content: space-between;
			align-items: center;
			box-sizing: content-box;

			.left {
				width: 26px;
				flex-shrink: 0;
				text-align: center;
			}



			.search-bar {
				display: flex;
				align-items: center;
				box-sizing: border-box;
				padding: 0 12px;
				gap: 7px;
				font-size: 14px;
				color: #eee;
				flex-grow: 1;

				input {
					flex-grow: 1;
				}
			}

			.container {}


			.right {
				flex-shrink: 0;
			}


		}
	}
</style>

在页面中使用组件:nav-bar

<!-- 上滑搜索栏 -->
		<view class="top-bar" :class="{active: showTopBar}">
			<!-- 搜索 -->
			<nav-bar search disabled searchBackground="rgba(255,255,255,0.9)" searchColor="#999"  @search="toSearch(null)" />
			<!-- 分类 -->
			<ProductCategory v-show="categoryShow" />
		</view>

  • 0
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值