1. 第一张图是简单的tab切换
  2. 第二张图用于可滑动的tab列表(tab比较多的时候,还想实现tab导航和内容联动的效果)2021.9.2 更
    在这里插入图片描述 请添加图片描述

1. 简单的tab切换:

判断当前点击的下标(index)是否和激活(act)相等,相等就添加激活样式……

1、 html

<view>
		<!-- tab栏切换动态改变激活样式 -->
		<view class="nav">
			<view class="nav-list" v-for="(item,index) in list" :key="item.id" @tap="changeAct(item)">

				<!-- 激活样式名字是红色 判断act==index 和act==item.id都行-->
				<view :class="[act==index?'name':'']">
					{{item.name}}
				</view>
				<!-- 名字下面的横线 -->
				<view :class="[act==index?'line':'']">
				</view>
			</view>

		</view>
		
		<!-- 内容的改变 -->
		<view class="content">
			<view class="">
				{{content.id}}
			</view>
			<view class="">
				{{content.name}}
			</view>
		</view>
	</view>

2、JavaScript

<script>
	export default {
		data() {
			return {
				// 默认激活样式是第一个
				act: 0,

				list: [{
						id: 0,
						name: '吃饭'
					},
					{
						id: 1,
						name: '学习'
					},
					{
						id: 2,
						name: '睡觉'
					}

				],
				content: ''
			};
		},
		methods: {
			changeAct(item) {
				// 激活样式是当前点击的对应下标--list中对应id
				this.act = item.id;

				// 可以根据点击事件改变内容
				this.content = item
			}
		},
		onShow() {
			// 页面默认显示的是list列表中第一条数据
			this.content = this.list[0]
		}
	}
</script>

3、css

<style scoped>
	.nav {
		height: 100rpx;
		display: flex;
		align-items: center;
		justify-content: space-around;
		background-color: rgba(0, 0, 0, .8);
		font-size: 30rpx;
		color: orange;
		letter-spacing: 2.14rpx;
	}

	.nav-list {
		width: 65rpx;
		height: 100%;
		margin-top: 40rpx;
		opacity: .9;
	}

	.nav-list .name {
		color: red;
	}

	.nav-list .line {
		margin-top: 10rpx;
		width: 65rpx;
		height: 4rpx;
		background-color: red;
	}

	/* 内容 */
	.content {
		margin-top: 40rpx;
	}
</style>

2. 联动的效果代码

(这种方法很容易耗性能,大体实现过程是这样的)

2.1 简单思路:

  1. tab列表使用scroll-view设置为x轴方向滚动、利用scroll-into-viewid跳转到对应的tab项。
  2. 内容区使用swiper是用于左右切换效果的,然后swiper中又嵌套了scroll-view是用于y轴方向滑动的。swiper的切换是根据current切换对应的轮播项的。

2.2. scrollH的高度获取(重点)

  1. 可使用窗口高度windowHeight减去你自己写的的tab项的高度就是内容区域可滑动的高度了。
  • 如果你取消了原生导航栏,记着把你自定义导航栏的高度也减掉
this.scrollH = res.windowHeight - uni.upx2px(100)-uni.upx2px(自定义导航的高度)
  • windowHeight不包含NavigationBarTabBar的高度
  • 高度相关信息,要放在 onReady 里获取
  1. scrollH:轮播swiper的高度和scroll-view的高度要设置成一样的。
  • 如果刚开始不太理解这个内容区域的滑动高度scrollH到底是多少,你自己可以尝试下不减去tab高度,滑动效果是什么样的……就懂了

2.3 页面触底事件

  • 内容区域的触底事件:一般用于加载更多,分页请求数据……
  • 此时如果你使用页面生命周期onReachBottom检测触底事件是不行滴 ,因为内容区是用scroll-view包裹的,只能使用scroll-view组件上的触底方法……,才能检测的到
  • @scrolltolower:滚动到底部/右边,会触发 scrolltolower 事件

scroll-view官网介绍

2.4 代码

1. HTMl

<template>
	<view>
		<!-- 根据scrollinto和:id="'tab'+index"切换下方轮播 -->
		<scroll-view scroll-x="true" class="scroll-row" :scroll-into-view="scrollinto" :scroll-with-animation="true">
			<view v-for="(item,index) in tabBars" :key="index" :id="'tab'+index"  class="scroll-row-item"
				 @click="changeTab(index)">
				<!-- 文字内容 -->
					<view  :class="tabIndex==index? 'scroll-row-item-act':''">
						{{item.name}}
					</view>
			</view>
		</scroll-view>

		<!--  滑块内容 对应的是顶部选项卡的切换 :current="tabIndex"  设置的是y方向上可以滚动-->
		<swiper :current="tabIndex" @change="onChangeSwiperTab" :style="{height:scrollH+'px'}">
			<swiper-item v-for="(item,index) in tabBars" :key="index">
				<!-- 垂直滚动区域  scroll和swiper的高度都要给且是一样的高度-->
				<scroll-view scroll-y="true" :style="{height:scrollH+'px'}"  @scrolltolower="lower">
					<!-- 可垂直滚动区域 显示真正内容-->
					{{item.name}}
					<view class="" v-for="(item2,index2) in 30" :key="index2">
						{{item2}}
					</view>
				</scroll-view>
			</swiper-item>
		</swiper>
	</view>
</template>

2. JavaScript+Css

<script>
	export default {
		data() {
			return {
				scrollinto: 'tab0', //默认是第一个推荐 tab 0
				scrollH: 0,//轮播嵌套的内容的滚动区域高度!一定要加这个高度否则动不了
				tabIndex: 0, //当前激活tabIndex
				tabBars: [{
						name: '凉拌洋葱'
					},
					{
						name: '南瓜粥'
					},
					{
						name: '酸辣土豆丝'
					},
					{
						name: '西红柿炒鸡蛋'
					},
					{
						name: '酸菜鱼'
					},
					{
						name: '糖醋排骨'
					},
					{
						name: '糖醋鱼'
					},
					{
						name: '鱼香肉丝'
					},
				]
			}
		},
		onReady () {
			// 获取可滚动区域的高度:视口高度 - tabbar切换卡高度就是剩余的内容可滚动的。
			//如果你使用取消了原生导航栏,记着把你自定义导航栏的高度也减掉哦
			uni.getSystemInfo({
				success: (res) => {
					this.scrollH = res.windowHeight - uni.upx2px(100)
				}
			})
		},
		methods: {
			// tab选项卡切换轮播
			changeTab(index) {
				// 点击的还是当前数据的时候直接return
				if (this.tabIndex == index) {
					return
				}
				this.tabIndex = index
				// 跟着滑动了要
				this.scrollinto = 'tab' + index
			},
			// 轮播去切换tab列表
			onChangeSwiperTab(e) {
				this.changeTab(e.detail.current)
				// this.tabIndex=e.detail.current
			},
			lower(){
				console.log('滚动到底部了,可以分页请求数据,加载更多');
			}
		}
	}
</script>

<style scoped>
	.scroll-row {
		height: 100rpx;
		line-height: 100rpx;
		background-color: #555555;
		
		padding-left: 30rpx;
	}
	.scroll-row-item {
		margin-right: 40rpx;
		color: #FFFFFF;
	}
	/* 当前tab激活的样式 */
	.scroll-row-item-act {
		color: #69eb4b;
	}
</style>

3. 最好使用官网的新闻模板nvue

第二种方法使用起来很容易耗性能,官方是这样子说滴:

如需要左右滑动的长列表,请在HBuilderX新建uni-app项目选新闻模板,那是一个标杆实现。自己用swiper和scroll-view做很容易引发性能问题。

uniapp官网demo演示
在这里插入图片描述

  • 文件位置:你新建的项目名/pages/template/tabbar/tabbar.nvue,这是一个nvue文件。
  • 其实看下官方的这个新闻模板大致思想是将内容区y轴方向的滚动scroll-view换成了nvuelist和cell渲染的方式,使用list组件确实好用,渲染速度也很快。
Logo

基于 Vue 的企业级 UI 组件库和中后台系统解决方案,为数万开发者服务。

更多推荐