uni横向tab切换+list实现tab切换长列表
最近在做这个功能第⼀次写踩了很多坑看了很多⽂章,下⾯整合了⼏篇和⾃⼰的见解代码
⽂章参考
还有些⽂章找不到⽹址了不要介意
横向tab选项卡切换列表⼀般是⽤swiper 加 -view实现的
但是scroll-view官⽅都说了不适合⽤来放长列表!
如果数据很少、列表很短,怎么写都没关系。但是数据多的时候scroll-view 这个组件如果超出预定区域后就会出现滚动条来进⾏滚动,滚
动查看数据⼜或者在配合监听到底加载更多的时候,会出现滑动卡顿,不流畅等问题。
tab选项卡没什么性能上的问题就不说了,插件市场很多随便下我⽤的是稍作了⼀点改动
如何优化整个页⾯的性能呢?答案就是使⽤原⽣渲染的nvue页⾯,同时使⽤专门⽤来渲染长列表的<list>组件。可以参考uni⾃家的hello模
板⾥项⽬,虽然插件市场也有其他前端模拟的下拉刷新,但性能不佳。
使⽤nvue的原⽣性能,它会⾃动处理释放优化⾮可视区的数据。还可以缓存列,只要看过这⼀页,再进去时内容是还在的。⼀般⼩程序的
⼤⼚案例⾥,的长列表都是这种做法。
下⾯放了⼀下我的代码
tablist.nvue
<template>
<view class="tabs">
<uni-arch-bar
冬天泡脚的好处radius="5"
placeholder="搜车牌号/企业名称"
v-model="archValue"
clearButton="auto"
cancelButton="none"
bgColor="#ffffff"
@input="iptSearch"
@clear="iptClear"
/>
<wuc-tab :tab-list="tabList" textFlex :tabCur.sync="tabIndex" tab-class="text-center fixed bg-white" lect-class="text-orange" @change="tabChange"></wuc-tab> <swiper class="tab-box" :current="tabIndex" :duration="300" @change="onswiperchange">
<swiper-item class="swiper-item" v-for="(page, index) in tabList" :key="index">
<newsPage class="page-item" :tabid="wsid" :ref="'page' + index"></newsPage>
</swiper-item>
</swiper>
</view>
</template>
<script>
import newsPage from './news-page.nvue';
// 缓存每页最多
const MAX_CACHE_DATA = 100;
// 缓存页签数量
const MAX_CACHE_PAGE = 4;
export default {
components: {
newsPage
},
data() {
return {
archValue:'',
archValue:'',
tabList: [
{
id: "tab01",
name: '最新',
newsid: 1
班干部的作用
}, {
id: "tab02",
name: '⼤公司',
newsid: 2
}, {
id: "tab03",
name: '内容',
newsid: 3
}, {
id: "tab04",
name: '消费',
newsid: 4
},
],
tabIndex: 0,
cacheTab: [],
isTap: fal
}
},
onReady() {
/
/每项对应列表
this.pageList = [];
for (var i = 0; i < this.tabList.length; i++) {
let item = this.$refs['page' + i]
if (Array.isArray(item)) {
this.pageList.push(item[0])
} el {
this.pageList.push(item)
}
}
//切换tab
this.switchTab(this.tabIndex);
},
methods: {
tabChange(index){
this.switchTab(index);
},
onswiperchange(e) {
// 注意:百度⼩程序会触发2次
let index = e.target.current || e.detail.current;
this.switchTab(index);
},
switchTab(index) {
//对应页没有数据就取加载数据
if (this.pageList[index].dataList.length === 0) {
this.loadTabData(index);
}
if (this.tabIndex === index) {
return;
}
// 缓存 tabId
if (this.pageList[this.tabIndex].dataList.length > MAX_CACHE_DATA) { let isExist = this.cacheTab.indexOf(this.tabIndex);
if (isExist < 0) {
this.cacheTab.push(this.tabIndex);
}
}
this.tabIndex = index;
// 释放 tabId
if (this.cacheTab.length > MAX_CACHE_PAGE) { let cacheIndex = this.cacheTab[0];
this.clearTabData(cacheIndex);
this.cacheTab.splice(0, 1);
}
},
loadTabData(index) {
this.pageList[index].loadData(true);
},
clearTabData(index) {
this.pageList[index].clear();
},
iptSearch(res){
console.log(res)
},
iptClear(res) {
console.log(res.value)
}
}
}
</script>
<style>
/* #ifndef APP-PLUS */
page {
width: 100%;
min-height: 100%;
display: flex;
}
/* #endif */
.
tabs {
flex: 1;
flex-direction: column;
临走前吻我
overflow: hidden;
/* #ifdef MP-ALIPAY || MP-BAIDU */
height: 100vh;
/* #endif */
}
.tab-bar {
/* #ifdef APP-PLUS */
width: 750rpx;
/
* #endif */
height: 42px;
flex-direction: row;
/* #ifndef APP-PLUS */
white-space: nowrap;
/* #endif */
}
/* #ifndef APP-NVUE */
.tab-bar ::-webkit-scrollbar {
display: none;
width: 0 !important;
height: 0 !important;
-webkit-appearance: none;
background: transparent;
}
/* #endif */
.scroll-view-indicator {
position: relative;
height: 2px;
background-color: transparent; }
.scroll-view-underline {
position: absolute;
top: 0;
bottom: 0;
width: 0;
background-color: #007AFF; }
.scroll-view-animation {
三角形面积计算transition-duration: 0.2s;
transition-property: left;
}
.tab-bar-line {
height: 1px;
background-color: #cccccc;
}
.tab-box {
flex: 1;
}
.uni-tab-item {
/* #ifndef APP-PLUS */
display: inline-block;
/* #endif */
flex-wrap: nowrap;
padding-left: 20px;
padding-right: 20px;
}
.uni-tab-item-title {
color: #555;
font-size: 15px;
height: 40px;
line-height: 40px;
flex-wrap: nowrap;
/* #ifndef APP-PLUS */
white-space: nowrap;
/* #endif */
}
.
uni-tab-item-title-active {
color: #007AFF;
}
.swiper-item {
农村精神文明建设flex: 1;
flex-direction: column;
}
.page-item {
flex: 1;
flex-direction: row;
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
bottom: 0;
}
</style>
newsPage.nvue
<template>
<view class="page-news">
<!-- #ifdef APP-NVUE -->
<list ref="list" class="listview" show-scrollbar="fal" loadmoreofft='5' @loadmore="loadMore">
<refresh :display="refreshing ? 'show':'hide'" @refresh="onrefresh" @pullingdown="onpullingdown" class='refresh'> <text class="loadingTitle">{{refreshText}}</text>
<loading-indicator></loading-indicator>
</refresh>
<cell v-for="(item, index) in dataList" :key="item.id">
<news-item :newsItem="item" @click="goDetail(item)"></news-item>
</cell>
<cell v-if="isLoading || dataList.length > 10">
<view class="loading-more">
<text class="loading-more-text">{{loadingText}}</text>
</view>
开业致辞简短精辟
</cell>
</list>
<!-- #endif -->
<!-- <no-data class="no-data" v-if="isNoData" @retry="loadMore"></no-data> 重试-->
<view class="no-data" v-if="isNoData">暂⽆数据</view>
</view>
</template>
<script>
import newsItem from './news-item.nvue';
import noData from '@/components/nodata.nvue';
export default {
components: {
noData,
newsItem,
},
props: {
tabid: {
type: [Number, String],
default: ''
}
},先抑后扬作文
data() {
return {
dataList: [],
pageIndex:1,
refreshing: fal,
澳门成人
refreshText: "",
isLoading: fal,
loadingText: '加载中...',
isNoData: fal,
}
},
created() {
this.pullTimer = null;
this.pageIndex=1;
},
methods: {
loadData(refresh) {
var _this = this;
var url,data,method;
if(this.tabid==1){
url='autobots/trafficAdvi/api/list.htm';