- 第一张图是简单的
tab
切换 - 第二张图用于可滑动的
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 简单思路:
tab
列表使用scroll-view
设置为x
轴方向滚动、利用scroll-into-view
和id
跳转到对应的tab
项。- 内容区使用
swiper
是用于左右切换效果的,然后swiper
中又嵌套了scroll-view
是用于y
轴方向滑动的。swiper
的切换是根据current
切换对应的轮播项的。
2.2. scrollH
的高度获取(重点)
- 可使用窗口高度
windowHeight
减去你自己写的的tab项
的高度就是内容区域可滑动的高度了。
- 如果你取消了原生导航栏,记着把你自定义导航栏的高度也减掉
this.scrollH = res.windowHeight - uni.upx2px(100)-uni.upx2px(自定义导航的高度)
windowHeight
不包含NavigationBar
和TabBar
的高度- 高度相关信息,要放在
onReady
里获取
scrollH
:轮播swiper
的高度和scroll-view
的高度要设置成一样的。
- 如果刚开始不太理解这个内容区域的滑动高度
scrollH
到底是多少,你自己可以尝试下不减去tab高度,滑动效果是什么样的……就懂了
2.3 页面触底事件
- 内容区域的触底事件:一般用于加载更多,分页请求数据……
- 此时如果你使用页面生命周期
onReachBottom
检测触底事件是不行滴 ,因为内容区是用scroll-view
包裹的,只能使用scroll-view
组件上的触底方法……,才能检测的到
@scrolltolower:
滚动到底部/右边,会触发 scrolltolower 事件
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做很容易引发性能问题。
- 文件位置:你新建的项目名
/pages/template/tabbar/tabbar.nvue
,这是一个nvue
文件。 - 其实看下官方的这个新闻模板大致思想是将内容区
y
轴方向的滚动scroll-view
换成了nvue
中list和cell
渲染的方式,使用list
组件确实好用,渲染速度也很快。