uniapp 顶部tab + 占满剩余高度的内容区域swiper


javascript 复制代码
<template>
	<view class="page-container">
		<!-- 顶部 Tab 栏 -->
		<view class="tabs-container">
			<scroll-view scroll-x class="tabs-scroll" :show-scrollbar="false">
				<view class="tabs">
					<view v-for="(tab, index) in tabs" :key="index" class="tab-item" :class="{ active: currentTab === index }"
						@click="switchTab(index)">
						{{ tab }}
						<view class="underline" v-if="currentTab === index"></view>
					</view>
				</view>
			</scroll-view>
		</view>

		<!-- 占满剩余高度的 swiper -->
		<swiper class="content-swiper" :current="currentTab" @change="onSwiperChange"
			:style="{ height: swiperHeight + 'px' }">
			<swiper-item v-for="(tab, index) in tabs" :key="index" class="swiper-item">
				<scroll-view scroll-y class="content-scroll" :show-scrollbar="false">
					<!-- 内容区域 -->
					<view class="content-box">
						<text class="title">{{ tab }} 的内容</text>
						<view v-for="item in 20" :key="item" class="demo-item">
							{{ tab }} 的内容项 {{ item }}
						</view>
					</view>
				</scroll-view>
			</swiper-item>
		</swiper>
	</view>
</template>

<script setup lang="ts">
	import { ref, getCurrentInstance } from 'vue'
	import { onLoad, onShow } from '@dcloudio/uni-app'

	const currentTab = ref(0)
	const tabs = ref(['全部', '矿场咨询', '安全教育', '岗位规范'])
	const swiperHeight = ref(500) // 初始高度,后续动态计算

	// 动态计算高度
	const calcSwiperHeight = () => {
		uni.getSystemInfo({
			success: (res) => {
				// 获取屏幕高度
				const screenHeight = res.windowHeight

				// 获取 tabs 容器高度(需要确保 DOM 已渲染)
				// 在 setup 中获取组件实例
				const instance = getCurrentInstance()
				const query = uni.createSelectorQuery().in(instance?.proxy)

				query.select('.tabs-container').boundingClientRect(data => {
					// 计算剩余高度 = 屏幕高度 - tabs 高度 - 安全区域(可选)
					const safeAreaInsets = res.safeAreaInsets?.top || 0
					swiperHeight.value = screenHeight - data.height - safeAreaInsets
				}).exec()
			}
		})
	}

	// 切换 Tab
	const switchTab = (index : number) => {
		currentTab.value = index
	}

	// 滑动 swiper 时同步 Tab
	const onSwiperChange = (e : any) => {
		currentTab.value = e.detail.current
	}

	// 初始化时计算高度
	onLoad(() => {
		calcSwiperHeight()
	})
</script>

<style scoped lang="scss">
	/* 页面容器 */
	.page-container {
		height: 100vh;
		display: flex;
		flex-direction: column;
	}

	/* 顶部 Tab 样式 */
	.tabs-container {
		position: sticky;
		top: 0;
		background: #fff;
		z-index: 999;
		box-shadow: 0 2rpx 6rpx rgba(0, 0, 0, 0.1);
		/* 确保 tabs 容器高度固定 */
		height: 90rpx;
	}

	/* swiper 容器 */
	.content-swiper {
		flex: 1;
		width: 100%;
	}

	/* swiper-item 内部滚动区域 */
	.content-scroll {
		height: 100%;
		padding: 30rpx;
		box-sizing: border-box;
	}

	/* 内容区域样式 */
	.content-box {
		background: #f5f5f5;
		border-radius: 16rpx;
		padding: 30rpx;
	}

	.title {
		font-size: 32rpx;
		font-weight: bold;
		margin-bottom: 30rpx;
		display: block;
	}

	.demo-item {
		padding: 20rpx;
		margin-bottom: 20rpx;
		background: #fff;
		border-radius: 8rpx;
		box-shadow: 0 2rpx 6rpx rgba(0, 0, 0, 0.05);
	}

	/* Tab 样式 */
	.tabs-scroll {
		white-space: nowrap;
		width: 100%;
	}

	.tabs {
		display: inline-flex;
		padding: 20rpx 30rpx;
	}

	.tab-item {
		position: relative;
		padding: 20rpx 40rpx;
		font-size: 28rpx;
		color: #666;
		transition: all 0.3s;
	}

	.tab-item.active {
		color: #007AFF;
		font-weight: 500;
	}

	.underline {
		position: absolute;
		bottom: 0;
		left: 50%;
		transform: translateX(-50%);
		width: 60%;
		height: 6rpx;
		background: #007AFF;
		border-radius: 3rpx;
		animation: underlineShow 0.3s ease-out;
	}

	@keyframes underlineShow {
		from {
			width: 0;
			opacity: 0;
		}

		to {
			width: 60%;
			opacity: 1;
		}
	}
</style>
相关推荐
mCell5 小时前
GSAP ScrollTrigger 详解
前端·javascript·动效
gnip5 小时前
Node.js 子进程:child_process
前端·javascript
codingandsleeping10 小时前
使用orval自动拉取swagger文档并生成ts接口
前端·javascript
白水清风11 小时前
微前端学习记录(qiankun、wujie、micro-app)
前端·javascript·前端工程化
用户221520442780012 小时前
new、原型和原型链浅析
前端·javascript
阿星做前端12 小时前
coze源码解读: space develop 页面
前端·javascript
叫我小窝吧12 小时前
Promise 的使用
前端·javascript
前端康师傅13 小时前
JavaScript 作用域
前端·javascript
云枫晖13 小时前
JS核心知识-事件循环
前端·javascript
eason_fan14 小时前
Git 大小写敏感性问题:一次组件重命名引发的CI构建失败
前端·javascript