uni-app前端处理瀑布流V2写法

发布于:2025-03-31 ⋅ 阅读:(23) ⋅ 点赞:(0)

如果后端返回的数据是:

[{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}]  这个形式一次性返回的话,前端要怎么处理分页并持续加载更多,下面将一步一步展开

本文用到了 uniapp 提供的 scroll-view : 滚动 , 以及 uview 提供的 u-loadmore : 加载更多动画

 

 

目录

一:定义滚动标签

二: 在Style中添加样式,设定滚动高度

三:添加触发滚动相关事件

最后整体代码(由于数据为假,仅供参考,部分地方需要变动地方已标出,需要自己变动):


 

一:定义滚动标签

<!-- 开启滚动 -->
<!--
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                = 设定高度使容器具备处于可上下滑动状态 =
     scroll-y: *开启纵向滚动
     class: *定义滚动的区域容器,里边必须指定高度,否则无法产生滚动行为
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                       = 用于监听触发回到顶部功能 =
     :scroll-top: *设置竖向滚动条位置(主要用于回到指定/顶部的位置)
     @scroll: *滚动时触发   
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                     = 用于监听触发持续加载更多功能 =
     lower-threshold: *距离底部多少高度时触发 scrolltolower 事件
     @scrolltolower: *滚动到底部触发事件
     
-->

<scroll-view
	scroll-y
	class="peiZhen-scroll-container"
    :scroll-top="scrollTop"
    @scroll="onScroll"
	lower-threshold="150"
	@scrolltolower="onScrollToLower">
    <view>
        这里放入自己要进行滚动的内容
    </view>
    <u-loadmore :status="loadStatus" @loadmore="loadMore"></u-loadmore>
    <view class="back-top" @click="goTop">回到顶部</view>
</scroll-view>

二: 在Style中添加样式,设定滚动高度

/* 开启瀑布流容器 */
.peiZhen-scroll-container {
	height: calc(100vh - 600rpx);
	width: 100%;
}

/* 回到顶部 */
.back-top{
	position: fixed;
	bottom: 100rpx;
	right: 20rpx;
	background-color: #3AD3AE;
	color: #FFFFFF;
	padding: 10rpx 20rpx;
	border-radius: 10rpx;
}

三:添加触发滚动相关事件

<script>
// getReviews: API接口数据
import { getReviews } from '@/api/xx/xx.js';
    export default {
		data() {
			return {
                // 此处主要用于滚动条级内容回到初始地方
                scrollTop:0,                               //设置竖向滚动条位置
                oldScrollTop:0                             //用于存储滚动条位置

                // 此处用于开启滚动并持续加载
                pageNum: 1,                                //请求第一页
                pageSize: 6,                               //初始加载6个
                loadMoreSize: 5,                           //每次加载更多时每次加载5个
                loadStatus: 'loadmore',                    //加载状态,默认文字显示 "加载更多"
                isLoading: false,                          //是否开启loading效果,默认 "不开启"
                isInitialLoad: true,                       //是否是第一次加载,默认 "第一次加载"
                这里填您API接口中获取到数据: [],             //如上述开头提到的数组[{},{}....]
                这里填您需要累加数据(可随意填写): [],     //当前显示的服务评价数据
            }
        },
        methods:{
            /**
			 * 回到顶部功能
			 */
			onScroll(e) {
				this.oldScrollTop = e.detail.scrollTop;
			},
			goTop() {
				this.scrollTop = this.oldScrollTop;
				this.$nextTick(() => {
					this.scrollTop = 0;
				});
			},


           /**
			 * 滚动到底部lower-threshold指定的150距离时触发加载更多事件
			 */
			onScrollToLower() {
                console.log('滚动到底部')
                // *滚动到指定150距离位置,开始加载更多数据
				this.loadMore();
			},
            loadMore(){
                // *首先判断加载状态是否是  nomore: 不加载 或 isLoading: 不开启加载转圈效果
                if(this.loadStatus === 'nomore' || this.isLoading) return;

                // *走到这步,就是需要加载和开启加载转圈效果,那我们就设置一下状态
                this.loadStatus = 'loading';    //加载中
                this.isLoading = true;          //开启转圈效果

                // *根据是否是初始加载决定使用哪个 (初始加载话pageSize默认显示6个, 否则使用loadMoreSize持续加载5个)
                const currentPageSize = this.isInitialLoad ? this.pageSize : this.loadMoreSize;

                // *计算起始和结束索引
				// start: 如果是初始加载, 则从0开始, 否则从当前页码减1乘以每页显示数量加上初始加载数量开始	
				// end: 如果是初始加载, 则显示初始加载数量, 否则从当前页码乘以每页显示数量加上初始加载数量开始
                const start = this.isInitialLoad ? 0 : (this.pageNum - 1) * this.loadMoreSize + this.pageSize;
				const end = this.isInitialLoad ? this.pageSize : start + this.loadMoreSize;

                // *从所有数据中获取当前页数据
				const currentPageData = this.这里填您API接口中获取到数据.slice(start, end);

                // *判断当前页数据是否 < 所有页显示数量, 或者结束索引是否 >= 所有数据长度
				if(currentPageData.length < currentPageSize || end >= this.这里填您API接口中获取到数据.length) {
                    // 处于还有数据,就将状态改为loadmore:持续加载更多
					this.loadStatus = 'nomore';
				} else {
                    // 处于还有数据,就将状态改为loadmore:持续加载更多
					this.loadStatus = 'loadmore';
					if(this.isInitialLoad) {
                        // 如果第一次加载走到这步,将第一次加载状态改为false,表示之后将不再是第一次加载
						this.isInitialLoad = false;
					} else {
                        // 如果之后不是第一次加载,则页码+1
						this.pageNum++;
					}
				}

				// 瀑布流加载效果:延迟添加数据
				setTimeout(() => {
                    // 这里要实现前端处理瀑布流,就要进行过滤,[第一个是这里填您需要累加数据(可随意填写),第二个不变]
					this.这里填您需要累加数据(可随意填写) = [...这里填您需要累加数据(可随意填写), ...currentPageData];
					this.isLoading = false;
				}, 300);
            },
            /**
		     * 请求API接口(这里给个API接口示例)
		     */
            reviewsList(){
                getReviews().then(res => {
                    if(res.code == 200 && res.data && res.data.length > 0){
                        this.这里填您API接口中获取到数据 = res.data
                        // 主要作用是,有数据时,系统先加载第一页(默认6条数据),用户下拉到底部时,会触发loadMoreDetail函数加载更多数据(每次5条)
						this.这里填您需要累加数据(可随意填写) = [];		//清空当前显示的评价数据列表
						this.pageNum = 1; 					//重置页码为第1页
						this.isInitialLoad = true; 			//标记为初始加载状态
						this.loadStatus = 'loadmore'; 		//设置加载状态为"可以加载更多"
						this.loadMore();				    //触发加载更多数据 [最终导致数据累加显示this.这里填您API接口中获取到数据= [...this.这里填您API接口中获取到数据, ...currentPageData]]
                    }else{
                        this.这里填您API接口中获取到数据 = [];
						this.这里填您需要累加数据(可随意填写) = [];  //*清空当前显示的评价数据列表
						this.loadStatus = 'nomore';			      //*设置加载状态为"没有更多数据"	
                    }
                })
            }
        },
        mounted(){
			// 服务评价
			this.reviewsList();
		},
    }
</script>

最后整体代码(由于数据为假,仅供参考,部分地方需要变动地方已标出,需要自己变动):

<template>
    <!-- 开启滚动 -->
    <!--
         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                    = 设定高度使容器具备处于可上下滑动状态 =
         scroll-y: *开启纵向滚动
         class: *定义滚动的区域容器,里边必须指定高度,否则无法产生滚动行为
         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                           = 用于监听触发回到顶部功能 =
         :scroll-top: *设置竖向滚动条位置(主要用于回到指定/顶部的位置)
         @scroll: *滚动时触发   
         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                         = 用于监听触发持续加载更多功能 =
         lower-threshold: *距离底部多少高度时触发 scrolltolower 事件
         @scrolltolower: *滚动到底部触发事件
         
    -->

    <scroll-view
	    scroll-y
	    class="peiZhen-scroll-container"
        :scroll-top="scrollTop"
        @scroll="onScroll"
	    lower-threshold="150"
	    @scrolltolower="onScrollToLower">
        <view>
            这里放入自己要进行滚动的内容
            <view class="price-item" v-for="(item, index) in 这里填您需要累加数据(可随意填写)" :key="index">
                <view>{{ item.a }}</view>
				<view>{{ item.b }}</view>
				<view>{{ item.c }}</view>
				<view>{{ item.d }}</view>
            </view>
        </view>
        <u-loadmore :status="loadStatus" @loadmore="loadMore"></u-loadmore>
        <view class="back-top" @click="goTop">回到顶部</view>
    </scroll-view>
</tempalte>

<script>
// getReviews: API接口数据
import { getReviews } from '@/api/xx/xx.js';
    export default {
		data() {
			return {
                // 此处主要用于滚动条级内容回到初始地方
                scrollTop:0,                               //设置竖向滚动条位置
                oldScrollTop:0                             //用于存储滚动条位置

                // 此处用于开启滚动并持续加载
                pageNum: 1,                                //请求第一页
                pageSize: 6,                               //初始加载6个
                loadMoreSize: 5,                           //每次加载更多时每次加载5个
                loadStatus: 'loadmore',                    //加载状态,默认文字显示 "加载更多"
                isLoading: false,                          //是否开启loading效果,默认 "不开启"
                isInitialLoad: true,                       //是否是第一次加载,默认 "第一次加载"
                这里填您API接口中获取到数据: [],             //如上述开头提到的数组[{},{}....]
                这里填您需要累加数据(可随意填写): [],     //当前显示的服务评价数据
            }
        },
        methods:{
            /**
			 * 回到顶部功能
			 */
			onScroll(e) {
				this.oldScrollTop = e.detail.scrollTop;
			},
			goTop() {
				this.scrollTop = this.oldScrollTop;
				this.$nextTick(() => {
					this.scrollTop = 0;
				});
			},


           /**
			 * 滚动到底部lower-threshold指定的150距离时触发加载更多事件
			 */
			onScrollToLower() {
                console.log('滚动到底部')
                // *滚动到指定150距离位置,开始加载更多数据
				this.loadMore();
			},
            loadMore(){
                // *首先判断加载状态是否是  nomore: 不加载 或 isLoading: 不开启加载转圈效果
                if(this.loadStatus === 'nomore' || this.isLoading) return;

                // *走到这步,就是需要加载和开启加载转圈效果,那我们就设置一下状态
                this.loadStatus = 'loading';    //加载中
                this.isLoading = true;          //开启转圈效果

                // *根据是否是初始加载决定使用哪个 (初始加载话pageSize默认显示6个, 否则使用loadMoreSize持续加载5个)
                const currentPageSize = this.isInitialLoad ? this.pageSize : this.loadMoreSize;

                // *计算起始和结束索引
				// start: 如果是初始加载, 则从0开始, 否则从当前页码减1乘以每页显示数量加上初始加载数量开始	
				// end: 如果是初始加载, 则显示初始加载数量, 否则从当前页码乘以每页显示数量加上初始加载数量开始
                const start = this.isInitialLoad ? 0 : (this.pageNum - 1) * this.loadMoreSize + this.pageSize;
				const end = this.isInitialLoad ? this.pageSize : start + this.loadMoreSize;

                // *从所有数据中获取当前页数据
				const currentPageData = this.这里填您API接口中获取到数据.slice(start, end);

                // *判断当前页数据是否 < 所有页显示数量, 或者结束索引是否 >= 所有数据长度
				if(currentPageData.length < currentPageSize || end >= this.这里填您API接口中获取到数据.length) {
                    // 处于还有数据,就将状态改为loadmore:持续加载更多
					this.loadStatus = 'nomore';
				} else {
                    // 处于还有数据,就将状态改为loadmore:持续加载更多
					this.loadStatus = 'loadmore';
					if(this.isInitialLoad) {
                        // 如果第一次加载走到这步,将第一次加载状态改为false,表示之后将不再是第一次加载
						this.isInitialLoad = false;
					} else {
                        // 如果之后不是第一次加载,则页码+1
						this.pageNum++;
					}
				}

				// 瀑布流加载效果:延迟添加数据
				setTimeout(() => {
                    // 这里要实现前端处理瀑布流,就要进行过滤,[第一个是这里填您需要累加数据(可随意填写),第二个不变]
					this.这里填您需要累加数据(可随意填写) = [...这里填您需要累加数据(可随意填写), ...currentPageData];
					this.isLoading = false;
				}, 300);
            },
            /**
		     * 请求API接口(这里给个API接口示例)
		     */
            reviewsList(){
                getReviews().then(res => {
                    if(res.code == 200 && res.data && res.data.length > 0){
                        this.这里填您API接口中获取到数据 = res.data
                        // 主要作用是,有数据时,系统先加载第一页(默认6条数据),用户下拉到底部时,会触发loadMoreDetail函数加载更多数据(每次5条)
						this.这里填您需要累加数据(可随意填写) = [];		//清空当前显示的评价数据列表
						this.pageNum = 1; 					//重置页码为第1页
						this.isInitialLoad = true; 			//标记为初始加载状态
						this.loadStatus = 'loadmore'; 		//设置加载状态为"可以加载更多"
						this.loadMore();				    //触发加载更多数据 [最终导致数据累加显示this.这里填您API接口中获取到数据= [...this.这里填您API接口中获取到数据, ...currentPageData]]
                    }else{
                        this.这里填您API接口中获取到数据 = [];
						this.这里填您需要累加数据(可随意填写) = [];  //*清空当前显示的评价数据列表
						this.loadStatus = 'nomore';			      //*设置加载状态为"没有更多数据"	
                    }
                })
            }
        },
        mounted(){
			// 服务评价
			this.reviewsList();
		},
    }
</script>
<style>
    /* 开启瀑布流容器 */
    .peiZhen-scroll-container {
	    height: calc(100vh - 600rpx);
	    width: 100%;
    }

    /* 回到顶部 */
    .back-top{
	    position: fixed;
	    bottom: 100rpx;
	    right: 20rpx;
	    background-color: #3AD3AE;
	    color: #FFFFFF;
	    padding: 10rpx 20rpx;
	    border-radius: 10rpx;
    }
</style>