场景
uni-app平台的nvue。不是vue。
vue的长列表,优化的好,性能也不差的。如何优化 请看我的其他文字

关于官方给的实例
https://github.com/dcloudio/hello-uniapp/tree/master/pages/template/swiper-list-nvue
上方就是官方给的案例,但是代码很多,特别难以理解。
而且存在两个bug。一个是ios中子list无法滚动。另一个是下面提到的scrollToElement问题。不过这两个问题,本demo已经修复了

需求
页面高度>屏幕高度时,页面会滚动。但是页面的最底部是一个可以左右切换的长列表。
左右切换的元素肯定用 swiper
长列表的话,也只能用 list 或 waterfall
那么结构就是

<template><view>
	<view>我是页面的其中内容</view>
	<swiper>
		<swiper-item v-for="(value, key) in new Array(4)" :index="key">
			<waterfall ref="waterfall">
				<cell v-for="(item, index) in new Array(30)" :index="index">
					我是可以左右切换,和垂直滚动的内容
					左右切换由swiper		实现
					垂直滚动由waterfall	实现
				</cell>
			</waterfall>
		</swiper-item>
	</swiper>
</view></template>

但这样子肯定是不行的。当你下滑到页面底部时,会发现waterfallfu是无法实现垂直滚动的。

必须把页面的根目录改为list

<template><list id="pageId">
	<cell style="height: 500px;">
		<view>我是页面的其中内容</view>
	</cell>
	<cell>
		<swiper>
			<swiper-item v-for="(value, key) in new Array(4)" :index="key">
				<waterfall ref="waterfall">
					<cell v-for="(item, index) in new Array(30)" :index="index">
						我是可以左右切换,和垂直滚动的内容
						左右切换由swiper		实现
						垂直滚动由waterfall	实现
					</cell>
				</waterfall>
			</swiper-item>
		</swiper>
	</cell>
</list></template>

但其实还是不行的,因为还需要js的配合

this.$refs.waterfall[this.activeIndex].setSpecialEffects({
	id: 'pageId',
	headerHeight: 500//这里的高度等于waterfall上面的所有元素的高度
});

并且每次swiper切换都需要执行这个js逻辑

============================
还有一个问题,如果列表1已经滚动了一段距离了,再从列表1切换到列表2,就会产生一个bug,具体看下面视频文件
https://vkceyugu.cdn.bspapp.com/VKCEYUGU-bf16ecad-1cbc-421f-9785-8a609ca4eb52/66a22f8b-de5b-42c8-b041-55b169efffc2.mp4

所以切换完成之后,切换前的列表需要回到顶部,用的是scrollToElement,
但是scrollToElement只能实现最外围的list滚动到某个位置。不能实现子list滚动到某个位置。
想实现这个功能,只能让子list以组件的方式引入,然后在组件中使用scrollToElement,就可以操控子list回到顶部了

============================

下面是demo
demo.nvue

<template><list id="pageId" bounce="false" show-scrollbar="false" fixFreezing="true">
	<cell>
		<view class="" ref="header">
			<text style="line-height: 500px;background-color grey;">head</text>
			<scroll-view class="nav" scroll-x="true" show-scrollbar="false" @scroll="scrollLeft = $event.detail.scrollLeft">
				<text ref="navItem" :class="['text', {active: index === activeIndex}]" v-for="(value, index) in navList" @click="activeIndex = index">列表{{index}}</text>
				<view class="xian" :style="{left: navXianLeft+'px',width: navXianWidth+'px'}"></view>
			</scroll-view>
		</view>
		<swiper class="swiper" :current="activeIndex" :style="{height: swiperHeight+'px'}" @change="change">
			<swiper-item class="swiperItem" v-for="(value, index) in navList" :key="index">
				<demoList ref="demoList" :height="swiperHeight" :index="index" :dataList="dataList"></demoList>
			</swiper-item>
		</swiper>
	</cell>
</list></template>
<script>
// #ifdef APP-NVUE
	const dom = weex.requireModule('dom')
// #endif
import demoList from '@/components/demoList.nvue'
export default {
	components: {demoList},
	data(){
		return {
			activeIndex: 0,
			swiperHeight: 100,
			navList: [],
			dataList: [],
			navXianLeft: 0,
			navXianWidth: 0,
			scrollLeft: 0
		}
	},
	methods: {
		change: function(event){
			this.activeIndex = event.detail.current;
			this.xian()
		},
		xian: function(){//nav下面的那条线的水平位置调整
			dom.getComponentRect(this.$refs.navItem[this.activeIndex], (option) => {
				this.navXianLeft = option.size.left + this.scrollLeft
				this.navXianWidth = option.size.width
			})
		},
		xiding: function(index){//吸顶
			dom.getComponentRect(this.$refs.header, (option) => {
				this.$refs.demoList[index].qiehuan(option.size.height)
			})
		}
	},
	onLoad(){
		this.navList = new Array(4)
		this.dataList = new Array(30)
	},
	onReady(){
		this.swiperHeight = this.$store.state.htmlHeight
		this.xian()
		this.xiding(0)
	},
	watch: {
		'activeIndex': function(newValue, oldValue){
			this.$refs.demoList[oldValue].goTop()
			this.xiding(newValue)
		}
	}
}
</script>
<style lang="scss">
.nav{
	flex-direction: row;
	background-color: #FFF;
	.text{
		width: 300rpx;
		text-align: center;
		font-size: 30rpx;
		color: rgba(0,0,0,0.5);
		line-height: 64rpx;
		&.active{
			color: #000;
		}
		
	}
	.xian{
		position: absolute;
		bottom: 0;
		height: 4rpx;
		background-color: blue;
	}
}
</style>

demoList.nvue

<template><waterfall ref="list" bounce="true" show-scrollbar="false" column-count="2" fixFreezing="true">
	<!-- waterfall 属性说明
			bounce			=	回弹效果,ios中list嵌套的list(或waterfall),必须设置bounce为true。否则子list无法滚动
			fixFreezing		=	ios才需要配置的,具体作用不详。官方说要配置
			show-scrollbar	=	显示滚动条
	-->
	<cell v-for="(value, key) in dataList" :key="key">
		<view v-if="key === 0" ref="goTop"></view>
		<text class="text">{{index}}=>{{key}}</text>
	</cell>
</waterfall></template>
<script>
// #ifdef APP-NVUE
const dom = weex.requireModule('dom')
// #endif
export default {
	props:{swiperHeight: Number,index: Number,dataList: Array},
	data(){return {}},
	methods: {
		qiehuan: function(height){
			this.$refs.list.setSpecialEffects({
				id: 'pageId',
				headerHeight: height
			});
		},
		goTop: function(){
			dom.scrollToElement(this.$refs.goTop[0], {
				animated: false//无动画
			})
		}
	}
}
</script>
<style lang="scss">
.text{
	background-color: #ebebeb;
	margin-left: 12px;
	margin-right: 12px;
	margin-top: 12px;
	padding: 20px;
	background-color: #fff;
	border-radius: 5px;
}
</style>

完整的工程文件
https://vkceyugu.cdn.bspapp.com/VKCEYUGU-bf16ecad-1cbc-421f-9785-8a609ca4eb52/04eb4cb2-0d16-485e-a5ed-3d2d7501b22e.zip

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐