更新记录
1.0.0(2023-09-07)
下载此版本
自定义tab导航栏,支持多种样式,支持h5,小程序,App
平台兼容性
App |
快应用 |
微信小程序 |
支付宝小程序 |
百度小程序 |
字节小程序 |
QQ小程序 |
HBuilderX 3.1.0 app-vue |
× |
√ |
× |
× |
× |
× |
钉钉小程序 |
快手小程序 |
飞书小程序 |
京东小程序 |
× |
× |
× |
× |
H5-Safari |
Android Browser |
微信浏览器(Android) |
QQ浏览器(Android) |
Chrome |
IE |
Edge |
Firefox |
PC-Safari |
√ |
√ |
√ |
√ |
√ |
√ |
√ |
√ |
√ |
unq-tabs
<!-- tabs栏 -->
<!-- 传入 :config="{textColor:'#00ff00'}" 能定制相应的主题 -->
<unq-tabs ref="unqTabsRefs" :tabData="tabData" :defaultIndex="currentIndex" @tabsClick="tabsClick" />
<!-- list视图 -->
<!--
5.让list 具备左右切换的能力
5.1:思考如何让 list 拥有左右切换的能力
解决:使用Swiper对其进行改造
5.2:问题1 - list 列表的高度展示错误
原因:没有为Swiper指定高度
解决:计算出每个item的高度,然后叠加到一起
5.3:问题2-切换tab时,list的卡顿问题
原因:Swiper 动画未完成时,就获取数据 渲染DOM
解决:Swiper 动画完成之后,获取数据,渲染DOM
6.完成list 与 tabs联动的能力
6.1 tabs 切换时,Swiper 联动切换
6.2 Swiper 切换时,tabs 联动切换
-->
<!--
功能补充:
1.tabs 具备吸顶的效果
2.控制列表滚动位置
2.1 当用户滚动页面之后
2.2 切换 tabs 时,让页面的滚动位置返回为 tabs吸顶的位置
-->
<!-- current 表示当前展示哪个 swiperItem @animationfinish 动画结束时会触发 animationfinish 事件, @change current 改变时会触发 change 事件-->
<swiper
class="swiper"
:style="{ height: swiperHeightData[currentIndex] + 'px' }"
:current="currentIndex"
@animationfinish="onSwiperEnd"
@change="omSwiperChange"
>
<!-- swiperItem 的数量,需要由 tabData进行决定 -->
<swiper-item class="swiper-item" v-for="(tabitem, tabindex) in tabData" :key="tabindex">
<!-- {{tabindex}} 就是currentIndex -->
<view>
<!-- Loading -->
<uni-load-more status="loading" v-if="isLoading"></uni-load-more>
<!-- 列表 -->
<block v-else>
<!-- todo 列表展示项 -->
</block>
</view>
</swiper-item>
</swiper>
export default {
data(){
return {
tabData: [
{
label:"热门",
value:'1',
},
{
label:"男装",
value:"2"
},
{
label:"女装",
value:"3"
},
{
label:"童装",
value:"4"
},
], // tabs列表类型
currentIndex: 0, // 默认tabs激活项
swiperHeightData: {}, // 缓存高度的计算结果。以index 为key,以对应的高度 为value
}
},
methods:{
// 请求热搜文章列表
async getHotList() {
/**
* 做数据缓存,请求过的数据不在请求
* 1. 没有获取过数据
* 1.1 展示loading
* 1.2 调用接口获取数据
* 1.3 把数据保存到本地
* 1.4 隐藏loading
*
* 2. 已经获取过数据(有了缓存之后)
* 2.1 直接渲染数据就可以了
* */
if (!this.listData[this.currentIndex]) {
// 判断当前listData[key]有没有值,有则已请求过数据
// 1
// 1.1
this.isLoading = true
// 1.2
const id = this.tabData[this.currentIndex].id
const { list } = await _getHotList(id)
// 1.3
this.listData[this.currentIndex] = list // 当前激活项做listData的key添加对应的list文章数据
// 1.4
this.isLoading = false
// console.log(this.listData)
// 渲染完成数据之后,计算Swiper高度
if (!this.swiperHeightData[this.currentIndex]) {
// 判断缓存高度
setTimeout(async () => {
this.currentSwiperHeight = await this.getCurrentSwiperHeight()
this.swiperHeightData[this.currentIndex] = this.currentSwiperHeight
/* #ifdef H5 */
this.$forceUpdate() // 解决H5中高度问题
/* #endif */
console.log(this.swiperHeightData[this.currentIndex])
}, 0)
}
}
},
/**
* 计算当前 Swiper高度
* */
getCurrentSwiperHeight() {
return new Promise((resolve, reject) => {
// 1.拿到所有的 item -> 异步
let sum = 0
const query = uni.createSelectorQuery().in(this)
query
.selectAll(`.hot-list-item${this.currentIndex}`)
.boundingClientRect(res => {
// 2.拿到所有 item 的高度
// 3.把所有的高度累加
console.log(res)
res.forEach((item, index) => {
sum += item.height
})
resolve(sum)
})
.exec()
})
},
// tabs激活项
tabsClick(index) {
// 保存tabs激活项
this.currentIndex = index
// this.getHotList() 点击切换时在Swiper动画完成时再调用请求数据进行渲染
},
/**
* 判断动画是否完成,执行渲染数据
* 让动画Swiper执行完成后再执行渲染数据
* */
onSwiperEnd() {
this.getHotList()
// console.log('swiper动画完成')
},
/**
* Swiper 切换时,tabs 联动切换
* */
omSwiperChange({ detail }) {
if (this.currentPageScrollTop > 125) {
uni.pageScrollTo({
scrollTop: 125,
duration: 200 // 滚动动画的时长,默认300ms,单位 ms
})
}
this.currentIndex = detail.current // 切换的激活项重新赋值
// 父调用子的方法 同步slider滑动快
setTimeout(() => {
// props是异步的,解决currentIndex最新值还没传给子组件去计算最新的slider left值
this.$refs.unqTabsRefs.tobToIndex()
}, 0)
// console.log('切换了',this.$refs.unqTabsRefs.activeIndex)
},
}
}