小白总结uniapp自定义导航栏(可点击可左右滑动切换页面)

翻出来之前写的代码,那时候我还不知道动态类,写的很累赘,今天想着优化一下,总结并对比一下两次的写法

确定需求

导航的设计图:

目标:实现点击和左右滑动切换导航

分析需求

原生的顶栏无法做到,需要自定义导航,于是我查看uniapp官方文档:

链接:https://uniapp.dcloud.net.cn/collocation/pages.html#customnav

在这要注意一个问题,当我们取消默认导航选择自定义导航时,非H5端,手机顶部状态栏区域会被页面内容覆盖

比如这样:

官方文档里给了详细的解释,照着文档就可以解决:

实现

方案一

方案一是我最开始写的,切换的是组件页面,适用于各种场景,但比较繁琐,不够简洁,不想看的小伙伴可直接看方案二!!

方案一完整代码:

<template>
	<view>
		<view class="status_bar">
			<!-- 状态栏占位 -->
		</view>
		<view class="container">
			<!-- 搜索/导航 -->
			<view class="top">
				<view class="tabTop">
					<uni-icons type="search" size="30" color="#fff" style="padding-left: 30rpx;"></uni-icons>
					<view class="title">
						<text class="follow" @tap="onFollow" :style="clickFollowStyle">关注</text>
						<text class="square" @tap="onSquare" :style="clickSquareStyle">广场</text>
					</view>
				</view>
			</view>

			<!-- 广场 -->
			<view class="squareMain" v-if="isSquare===1">
				<!-- 导航栏 -->
				<view class="tabBar">
					<text v-for="(i,index) in tabBarData" :key="index" @tap="onclick(index)"
						:style="i.style">{{i.text}}</text>
				</view>
				<swiper :current="swiperIndex" style="height: calc(100vh - 260rpx);" @change=handelSwiper>
					<!-- 根据条件显示各个组件页面 -->
					<swiper-item>
						<find v-if="![1, 2, 3, 4, 5, 6].includes(swiperIndex)" />
					</swiper-item>
					<swiper-item>
						<city v-if="swiperIndex===1" />
					</swiper-item>
					<swiper-item>
						<walking v-if="swiperIndex===2" />
					</swiper-item>
					<swiper-item>
						<sea v-if="swiperIndex===3" />
					</swiper-item>
					<swiper-item>
						<play v-if="swiperIndex===4" />
					</swiper-item>
					<swiper-item>
						<hotel v-if="swiperIndex===5" />
					</swiper-item>
					<swiper-item>
						<delicious v-if="swiperIndex===6" />
					</swiper-item>
				</swiper>
			</view>
			<!-- 关注 -->
			<view class="followMain" v-else>
				<follow />
			</view>
		</view>
	</view>
</template>

<script setup>
	import {
		ref,
		watch,
		onMounted,
	} from "vue";

	// 导入页面组件
	import find from "../../pages/community/find.vue"
	import city from "../../pages/community/city.vue"
	import walking from "../../pages/community/walking.vue"
	import sea from "../../pages/community/sea.vue"
	import play from "../../pages/community/play.vue"
	import hotel from "../../pages/community/hotel.vue"
	import delicious from "../../pages/community/delicious.vue"
	import follow from "../../pages/community/follow/follow.vue"

	//控制“关注”和“广场”
	const isSquare = ref(1)
	const clickFollowStyle = ref('color: #FFF;');
	const clickSquareStyle = ref('color: #7e9de2;')
	const onFollow = () => {
		isSquare.value = 0;
		clickFollowStyle.value = 'color: #7e9de2;';
		clickSquareStyle.value = 'color: #FFF;';
	}
	const onSquare = () => {
		isSquare.value = 1
		clickSquareStyle.value = 'color: #7e9de2;';
		clickFollowStyle.value = 'color: #FFF;';
	}

	const fold = ref("展开")
	
	// 广场导航
	const tabBarData = ref([{
			text: '发现',
			style: 'color:#7e9de2;border-bottom: 2px solid #7e9de2;'
		},
		{
			text: '城市',
			style: 'color: #fff;'
		},
		{
			text: '徒步',
			style: 'color: #fff;'
		},
		{
			text: '看海',
			style: 'color: #fff;'
		},
		{
			text: '玩乐',
			style: 'color: #fff;'
		},
		{
			text: '酒店',
			style: 'color: #fff;'
		},
		{
			text: '美食',
			style: 'color: #fff;'
		},
	])

	// 获取当前页面路径信息
	const pages = getCurrentPages()
	const currentPage = pages[pages.length - 1]
	console.log('当前页面路径:', currentPage.route)

	// 滑动触发导航
	const swiperIndex = ref()
	const handelSwiper = (e) => {
		console.log(e.detail.current);
		swiperIndex.value = e.detail.current
		// 导航初始样式
		tabBarData.value.forEach((item, i) => {
			item.style = 'color: #fff;';
		});
		// 滑动导航的样式
		tabBarData.value[e.detail.current].style =
			'color:#7e9de2;border-bottom: 2px solid #7e9de2;font - size: large;';
	}

	// 点击触发导航
	const tabIndex = ref()
	const onclick = (index) => {
		console.log(index);
		tabIndex.value = index
		swiperIndex.value = tabIndex.value
		// 导航初始样式
		tabBarData.value.forEach((item, i) => {
			item.style = 'color: #fff;';
		});
		// 点击导航后的样式
		tabBarData.value[index].style = 'color: #7e9de2;border-bottom: 2px solid #7e9de2;font - size: large;';
	}
</script>

<style scoped lang="scss">
	.status_bar {
		height: var(--status-bar-height);
		width: 100%;
	}

	.container {
		.top {
			position: fixed;
			top: var(--status-bar-height);
			margin-bottom: 10px;

			.tabTop {
				display: flex;
				width: 100vw;
				font-size: 40rpx;
				display: flex;
				align-items: center;
				margin-top: 10px;

				.title {
					flex: 1;
					text-align: center;
					padding: 18rpx 0;

					.follow {
						display: inline;
						margin: 0 30rpx 0 -90rpx
					}
				}
			}
		}

		.squareMain {
			.tabBar {
				display: flex;
				align-items: center;
				justify-content: space-around;
				margin: 10px 0;

				text {
					display: block;
					padding-bottom: 2px;
				}
			}

			position: fixed;
			width: 100vw;
			margin-top: 130rpx;
		}

		.followMain {
			position: static;
			margin-top: 130rpx;
		}
	}
</style>

方案二

这个方案是我在看其他博主写的文章时借鉴的思想,比较简练,该博主文章链接:

链接:http://t.csdnimg.cn/by5F0

该博主写的是关于微信小程序的。

借鉴该博主思想和AI助手,利用动态类重新实现。

完整代码:

<template>
	<view class="status_bar">
		<!-- 状态栏占位 -->
	</view>
	<view class="tabs-container">
		<view v-for="(tab, index) in tabList" :key="index" @tap="tabsOn(index)" :class="{ active: tabsId === index }"
			class="tab">{{ tab.title }}</view>
	</view>
	<swiper @change="slideOn" :current="tabsId">
		<swiper-item v-for="(tab, index) in tabList" :key="index">
			<view>{{ tab.title }} content</view>
		</swiper-item>
	</swiper>
</template>

<script setup>
	import {
		ref
	} from 'vue';

	const tabList = [{
			title: "发现",
			index: "0"
		},
		{
			title: "城市",
			index: "1"
		},
		{
			title: "徒步",
			index: "2"
		},
		{
			title: "看海",
			index: "3"
		},
		{
			title: "玩乐",
			index: "4"
		},
		{
			title: "酒店",
			index: "5"
		},
		{
			title: "美食",
			index: "6"
		}
	];

	const tabsId = ref(0);

	const slideOn = (e) => {
		tabsId.value = e.detail.current;
	};

	const tabsOn = (index) => {
		tabsId.value = index;
	};
</script>

<style scoped lang="scss">
	.status_bar {
		height: var(--status-bar-height);
		width: 100%;
	}

	.tabs-container {
		display: flex;
		justify-content: space-between;
		padding: 20px;

		.tab {
			padding: 10px;
		}

		.active {
			color: #7e9de2;
		}
	}
</style>

效果图:

结语

超级简练有没有,就应该这样写才对嘛,有了这种简单的再看之前写的,,enn,,,

有需要的再补充~

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值