无限滚动分页加载与下拉刷新技术探析:原理深度解读与实战应用详述

news2025/1/14 4:03:55

在这里插入图片描述

滚动分页加载(也称为无限滚动加载、滚动分页等)是一种常见的Web和移动端应用界面设计模式,用于在用户滚动到底部时自动加载下一页内容,而无需点击传统的分页按钮。这种设计旨在提供更加流畅、连续的浏览体验,减少用户交互步骤,尤其适合内容丰富的列表或瀑布流布局。本文详述了无限滚动分页加载与下拉刷新技术的原理,并以实战示例实际应用。

一、滚动分页加载

1、前端实现(Vue)

  • 滚动事件监听:使用JavaScript(或对应的库/框架,如Vue.js、React等)监听滚动事件,判断用户是否接近页面底部。常见的判断条件是滚动位置距离文档底部的距离小于一定阈值。

  • 请求发送:当满足加载条件时,向后端发送请求,请求参数通常包括当前加载的页码或数据偏移量、每页数据量等。

  • 内容插入与更新:收到后端返回的新数据后,将新内容动态添加到现有列表的末尾,同时可能伴有过渡动画效果。此外,需要更新相关状态(如当前页码、是否还有更多数据等)。

模板(HTML)
<template>
  <div id="content-container">
    <div v-for="item in items" :key="item.id">{{ item.content }}</div>
  </div>
  <div v-if="loading" class="loading-spinner">Loading...</div>
</template>

这里使用Vue的v-for指令遍历已加载的items数组,显示内容。同时,当loading状态为真时,显示加载提示。

样式(CSS)
.loading-spinner {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 50px;
  /* 其他样式... */
}
脚本(JavaScript)
<template>
  <div id="content-container">
    <div v-for="item in items" :key="item.id">{{ item.content }}</div>
  </div>
  <div v-if="loading" class="loading-spinner">Loading...</div>
</template>

<script>
import axios from 'axios';

export default {
  data() {
    return {
      items: [],
      currentPage: 1,
      itemsPerPage: 10,
      loading: false,
    };
  },
  mounted() {
    window.addEventListener('scroll', this.handleScroll);
    this.fetchData();
  },
  beforeDestroy() {
    window.removeEventListener('scroll', this.handleScroll);
  },
  methods: {
    handleScroll() {
      if (
        window.innerHeight + document.documentElement.scrollTop !==
        document.documentElement.offsetHeight
      ) {
        return;
      }
      this.loading = true;
      this.fetchData();
    },
    fetchData() {
      axios.get('/api/data', {
        params: {
          page: this.currentPage,
          limit: this.itemsPerPage,
          sort: "create_time"
        },
      })
        .then((response) => {
          if (response.data.length > 0) {
            this.items.push(...response.data);
            this.currentPage++;
          }
          this.loading = false;
        })
        .catch((error) => {
          console.error('Error fetching data:', error);
          this.loading = false;
        });
    },
  },
};
</script>

前端实现主要包括:

  1. 定义数据属性:items存储已加载的内容项,currentPageitemsPerPage用于分页参数,loading标识是否正在加载数据。
  2. 使用mounted生命周期钩子添加滚动事件监听器,beforeDestroy钩子移除监听器以避免内存泄漏。
  3. handleScroll方法在用户滚动至页面底部时触发,设置loadingtrue并调用fetchData
  4. fetchData函数通过axios发送GET请求到后端接口,携带当前页数和每页数量作为查询参数。
  5. 请求成功时,将新获取的数据项添加到items数组中,更新currentPage,并重置loading状态。若发生错误,显示错误信息并取消加载状态。

注:

  • 性能优化:无限滚动分页加载页面过多,在数据量比较大时,可以通过隐藏非可视区数据,优化页面性能。
  • 监听事件:在uniapp等中,页面可以监听onReachBottom,scroll-view组件可以监听@scrolltolower事件,来判断是否到达容器特定部位从而加载数据。

2、后端实现(Node.js with Express)

  • 接口设计:提供一个接受分页参数(如页码、每页数量、数据偏移量等)的API接口,用于返回对应页码的数据。

  • 数据处理:根据接收到的分页参数,从数据库或其他数据源中查询并返回相应数据。为了性能考虑,通常会使用分页查询语句。

  • 响应格式:返回的数据结构应包含实际数据(如列表项)以及可能需要的元信息,如总记录数(用于前端判断是否还有更多数据可加载)。

路由与控制器
const express = require('express');
const router = express.Router();
const DataModel = require('../models/DataModel');

router.get('/data', async (req, res) => {
  const page = parseInt(req.query.page) || 1;
  const sort = parseInt(req.query.sort) || "create_time";
  const limit = parseInt(req.query.limit) || 10;

  try {
    const results = await DataModel.find()
      .skip((page - 1) * limit)
      .sort(sort)
      .limit(limit);

    const totalItems = await DataModel.countDocuments();

    res.json({
      data: results,
      total: totalItems,
    });
  } catch (err) {
    console.error('Error fetching data:', err);
    res.status(500).json({ error: 'Internal server error' });
  }
});

module.exports = router;

后端实现主要包括:

  1. 使用Express定义/data路由。
  2. 从请求查询参数中提取pagesortlimit值。
  3. 使用Mongoose(假设使用MongoDB作为数据库)执行分页查询:
    • skip()跳过前几条记录((page - 1) * limit),相当于当前页之前的记录。
    • sort()记录排序方式。
    • limit()限制返回结果的数量为指定的每页数量(limit)。
  4. 计算数据总数(可选,用于前端显示总条数或判断是否还有更多数据)。
  5. 将查询结果和总条数一起返回给前端。

这样,前端Vue应用在用户滚动到页面底部时会触发后端接口请求,后端Node.js服务器根据请求参数返回相应分页的数据,前端接收到数据后将其添加到现有内容中,从而实现滚动分页加载的效果。

二、下拉刷新加载

下拉刷新(Pull-to-Refresh)是一种常见的交互设计模式,主要用于移动应用或网页中,允许用户通过下拉屏幕内容来触发数据的更新。以下是一些关于实现下拉刷新功能的要点:

  • 直观的视觉反馈:当用户开始下拉时,应提供清晰的视觉反馈,如箭头、加载动画、提示文字等,让用户明白当前操作正在触发数据刷新。在用户下拉到一定程度后(通常为视窗高度的一半左右),可显示更明确的刷新指示符,如旋转的加载图标和“刷新中…”的文字信息。

  • 触发动效:设计流畅且符合应用风格的动效,如下拉时内容跟随手指滑动,释放后回弹并显示加载动画。动效不仅增强用户体验,还能缓解用户等待数据加载时的焦虑感。

  • 刷新触发阈值:设置合理的触发刷新的阈值,既不要让用户感到下拉阻力过大,也不应过低导致误操作。一般而言,当用户下拉距离超过屏幕一定比例(如50%)时,激活刷新动作。

  • 刷新状态通知:在刷新过程中,应保持视觉反馈,如保持加载动画的显示,并可配合进度条或百分比显示刷新进度。刷新完成后,及时更新提示信息,如“刷新成功”或“无新内容”,并恢复初始状态。

  • 数据更新策略:确定刷新的数据范围和频率。可以是只加载最新数据,也可以是重新加载整个列表。对于实时性要求较高的应用,可考虑设置定时自动刷新或后台刷新机制。

  • 错误处理

    • 网络异常:在网络连接不稳定或服务器响应失败时,应显示相应的错误提示,如“网络连接失败,请检查网络后重试”。
    • 数据加载失败:如果刷新数据过程中出现问题,应告知用户加载失败并提供重试选项。
  • 无障碍设计:考虑为视障用户或使用辅助技术的用户提供替代交互方式,如通过双击或长按进行刷新,确保所有用户都能便捷地使用下拉刷新功能。

  • 性能优化:尽量减少刷新过程对应用性能的影响,如使用分页加载、懒加载等技术,避免一次性加载大量数据导致卡顿。同时,对刷新操作进行适当的节流或防抖处理,防止用户短时间内频繁触发刷新。

  • 一致性与自定义:在整个应用中,下拉刷新的样式、触发方式和反馈应保持一致。同时,考虑到品牌识别度和个性化需求,可以提供一定的自定义选项,如更改刷新图标、颜色等。

综上所述,实现一个优秀的下拉刷新功能需兼顾用户体验、功能性和技术性能,确保用户能够轻松、准确、高效地获取最新数据。

可以在前述基础上增加下拉刷新的逻辑。以下是详细实现与举例:

1、前端实现(Vue)

模板(HTML)

<template>
  <div ref="contentContainer" @touchstart.prevent="handleTouchStart" @touchmove.prevent="handleTouchMove" @touchend="handleTouchEnd">
    <div v-for="item in items" :key="item.id">{{ item.content }}</div>
  </div>
  <div v-if="loading" class="loading-spinner">Loading...</div>
  <div v-if="canRefresh && refreshing" class="refresh-spinner">Refreshing...</div>
</template>

这里添加了一个ref="contentContainer"以便在JS中获取元素,同时添加了下拉刷新相关的触摸事件监听器。当refreshing状态为真时,显示刷新提示。

样式(CSS)
.loading-spinner,
.refresh-spinner {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 50px;
  /* 其他样式... */
}

.refresh-spinner {
  /* 刷新提示的样式 */
}
脚本(JavaScript)
<template>
  <!-- ... -->
</template>

<script>
import axios from 'axios';

export default {
  data() {
    return {
      items: [],
      currentPage: 1,
      itemsPerPage: 10,
      loading: false,
      canRefresh: false,
      refreshing: false,
      startY: 0,
      moveY: 0,
      threshold:* window.innerHeight, // 下拉刷新阈值
    };
  },
  mounted() {
    this.$refs.contentContainer.addEventListener('scroll', this.handleScroll);
    window.addEventListener('resize', this.updateThreshold);
    this.updateThreshold(); // 初始化阈值
  },
  beforeDestroy() {
    this.$refs.contentContainer.removeEventListener('scroll', this.handleScroll);
    window.removeEventListener('resize', this.updateThreshold);
  },
  methods: {
    handleScroll(e) {
      const scrollTop = e.target.scrollTop;
      if (scrollTop === 0) {
        this.canRefresh = true;
      } else {
        this.canRefresh = false;
      }
    },
    updateThreshold() {
      this.threshold =* window.innerHeight;
    },
    handleTouchStart(e) {
      if (!this.canRefresh) return;
      this.startY = e.touches[0].clientY;
    },
    handleTouchMove(e) {
      if (!this.canRefresh) return;
      this.moveY = e.touches[0].clientY - this.startY;
      if (this.moveY > 0) {
        e.preventDefault();
        this.$refs.contentContainer.scrollTop = this.moveY / 2;
      }
    },
    handleTouchEnd() {
      if (!this.canRefresh || this.moveY <= 0) return;
      if (this.moveY > this.threshold) {
        this.refreshing = true;
        this.fetchData(true); // 添加一个参数表示刷新操作
      }
      this.moveY = 0;
    },
    fetchData(refresh = false) {
      // ...(同前文fetchData方法,略去重复部分)
      if (refresh) {
        this.items = [];
        this.currentPage = 1;
      }
      // ...(后续请求处理逻辑)
    },
  },
};
</script>

前端实现增加下拉刷新功能主要包括:

  1. 在数据属性中添加canRefresh(是否允许下拉刷新)、refreshing(是否正在刷新)、startY(触摸开始时的Y坐标)、moveY(当前触摸点与开始点的Y轴偏移)和threshold(触发刷新的阈值)。
  2. mounted钩子中添加窗口resize事件监听器,更新threshold值。
  3. 添加handleScroll方法,在滚动至顶部时允许下拉刷新,否则禁止。
  4. 添加触摸事件监听器:handleTouchStart记录开始触摸位置,handleTouchMove处理触摸移动(阻止默认滚动并模拟下拉效果),handleTouchEnd判断是否触发刷新并重置状态。
  5. 修改fetchData方法,接收一个refresh参数,当为true时清空已有数据并重置当前页,然后继续执行原有请求逻辑。

注:在uniapp等中,页面可以监听onPullDownRefresh,scroll-view可以设置refresher-enabled="true"监听@refresherrefresh事件,下拉刷新数据。

后端(Node.js with Express)

后端处理保持不变,只需处理前端发送的分页请求即可,无需关心是否为下拉刷新操作。

通过上述实现,前端Vue应用不仅具备滚动分页加载功能,还增加了下拉刷新机制。用户在页面顶部下拉超过一定距离时,会触发刷新操作,清除现有数据并重新加载第一页内容。同时,原有的滚动分页加载逻辑不受影响,用户向下滚动时仍能加载更多数据。

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1623427.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

人耳的七个效应

1、掩蔽效应 • 人们在安静环境中能够分辨出轻微的声音&#xff0c;即人耳对这个声音的听域很低&#xff0c;但在嘈杂的环境中轻微的声音就会被淹没掉&#xff0c;这时将轻微的声音增强才能听到。 • 这种在聆听时&#xff0c;一个声音的听阈因另一声音的出现而提高的现象&…

ThinkPad E14 Gen 4,R14 Gen 4,E15 Gen 4(21E3,21E4,21E5,21E6,21E7)原厂Win11系统恢复镜像下载

lenovo联想ThinkPad笔记本电脑原装出厂Windows11系统安装包&#xff0c;恢复出厂开箱状态一模一样 适用型号&#xff1a;ThinkPad E14 Gen 4,ThinkPad R14 Gen 4,ThinkPad E15 Gen 4 (21E3,21E4,21E5,21E6,21E7) 链接&#xff1a;https://pan.baidu.com/s/1QRHlg2yT_RFQ81Tg…

服务部署后出错怎么快速调试?试试JDWP协议

前言 原文链接&#xff1a;教你使用 JDWP 远程调试服务 在我们日常开发工作中&#xff0c;经常会遇到写好的代码线上出了问题&#xff0c;但是本地又无法复现&#xff0c;看着控制台输出的日志恨自己当初没有多打几条日志&#xff0c;然后追着日志一条一条查&#xff0c;不说…

安装 Nginx 的三种方式

通过 Nginx 源码安装需要提前准备的内容&#xff1a; GCC 编译器 Nginx 是使用 C 语言编写的程序&#xff0c;因此想要运行 Nginx 就需要安装一个编译工具 GCC 就是一个开源的编译器集合&#xff0c;用于处理各种各样的语言&#xff0c;其中就包含了 C 语言 使用命令 yum i…

python基础语法--列表

一、列表的概念 列表&#xff08;List&#xff09;是一种有序、可变、允许重复元素的数据结构。列表用于存储一组相关的元素&#xff0c;并且可以根据需要动态地进行增加、删除、修改和访问。以下是列表的主要特点和操作&#xff1a; 有序性&#xff1a; 列表中的元素是按照它…

工作与生活,如何找到平衡点,实现双赢?(2个简单工具答案一目了然)

前言 很多 35岁左右上有老下有小的程序员会陷入一个瓶颈期&#xff0c;在工作上想努力多赚钱&#xff0c;但是每天回到家 23 点&#xff0c;老婆孩子早已熟睡。好不容易周末有点休息时间&#xff0c;但是一个电话接一个&#xff0c;由于是生产问题还不得不接。 那么职场人应该如…

激活IDM下载器并配置百度网盘

前言&#xff1a; 最近想下载一些软件&#xff0c;奈何不充钱的百度网盘的速度实在太慢了&#xff0c;不到一个G的文件夹奈何下了一晚上&#xff0c;只能重新找一下idm的下载了。 但是idm的正版是需要收费的&#xff0c;所以有白嫖党的破解版就横空出世了。 正文&#xff1a…

【目标跟踪】ByteTrack详解与代码细节

文章目录 一、前言二、代码详解2.1、新起航迹2.2、预测2.3、匹配2.4、结果发布2.5、总结 三、流程图四、部署 一、前言 论文地址&#xff1a;https://arxiv.org/pdf/2110.06864.pdf git地址&#xff1a;https://github.com/ifzhang/ByteTrack ByteTrack 在是在 2021 年 10 月…

OpenAIGPT-4.5提前曝光?

OpenAI GPT-4.5的神秘面纱&#xff1a;科技界的震撼新篇章 在人工智能的世界里&#xff0c;每一次技术的飞跃都不仅仅是一次更新&#xff0c;而是对未来无限可能的探索。近日&#xff0c;科技巨头OpenAI似乎再次站在了这场革命的前沿&#xff0c;其潜在的新产品——GPT-4.5 Tur…

Https协议原理剖析【计算机网络】【三种加密方法 | CA证书 】

目录 一&#xff0c;fidler工具 前提知识 二&#xff0c;Https原理解析 1. 中间人攻击 2. 常见的加密方式 1&#xff09;. 对称加密 2&#xff09;. 非对称加密 对称加密 4&#xff09;. CA证书 1. 数据摘要 3. 数字签名 CA证书 理解数据签名 存在的安全疑问&am…

ubuntu ROS1 C++下使用免安装eigen库的方法

1、eigen库的定义及头文件介绍 Eigen是一个高层次的C 库&#xff0c;有效支持线性代数&#xff0c;矩阵和矢量运算&#xff0c;数值分析及其相关的算法。 2、获取eigen库安装包 下载地址&#xff1a;eigen库官网 &#xff0c;如下图所示&#xff1a; 下载最新版tar.bz2即可&…

嵌入式Linux driver开发实操(二十三):ASOC

ASoC的结构及嵌入到Linux音频框架 ALSA片上系统(ASoC)层的总体项目目标是为嵌入式片上系统处理器(如pxa2xx、au1x00、iMX等)和便携式音频编解码器提供更好的ALSA支持。在ASoC子系统之前,内核中对SoC音频有一些支持,但它有一些局限性: ->编解码器驱动程序通常与底层So…

甘特图是什么?如何利用其优化项目管理流程?

甘特图是项目管理软件中十分常见的功能&#xff0c;可以说每一个项目经理都要学会使用甘特图才能更好的交付项目。什么是甘特图&#xff1f;甘特图用来做什么&#xff1f;简单来说一种将项目任务与时间关系直观表示的图表&#xff0c;直观地展示了任务进度和持续时间。 一、甘特…

博睿数据亮相GOPS全球运维大会,Bonree ONE 2024春季正式版发布!

2024年4月25日&#xff0c;博睿数据 Bonree ONE 2024 春季正式版焕新发布。同时&#xff0c;博睿数据AIOps首席专家兼产品总监贺安辉携核心产品新一代一体化智能可观测平台 Bonree ONE 亮相第二十二届 GOPS 全球运维大会深圳站。 Bonree ONE 2024 春季版产品重点升级数据采集、…

7-30 字符串的冒泡排序

题目链接&#xff1a;7-30 字符串的冒泡排序 一. 题目 1. 题目 2. 输入输出样例 3. 限制 二、代码 1. 代码实现 #include <stdio.h> #include <string.h> #include <stdlib.h>// 获取输入的字符串 char **arrayGet(int len) {char **array;array malloc…

单链表实现通讯录

不过多赘述了 顺序表的增删查改-CSDN博客https://blog.csdn.net/bkmoo/article/details/137566495?spm1001.2014.3001.5502 使用顺序表实现通讯录-CSDN博客https://blog.csdn.net/bkmoo/article/details/137676561?spm1001.2014.3001.5502这里没有使用文件操作只是简单的使…

施耐德EOCR-DS3-60S电机保护器 5-60A 24-240VAC/DC

三和EOCR株式会社是韩国的电动机保护器生产企业&#xff0c;公司由金仁锡博士&#xff08;施耐德电气集团韩国执行官&#xff09;于1981年建立。 2001年&#xff0c;为了把企业发展成性的、战略性企业&#xff0c;随后加入了法国施耐德电气集团公司。 EOCR主要产品有电子式电…

没有文件服务器,头像存哪里合适

没有文件服务器&#xff0c;头像存哪里合适 1. 背景 之前有同学私信我说&#xff0c;他的项目只是想存个头像&#xff0c;没有别的文件存储需求&#xff0c;不想去用什么Fastdfs之类的方案搭建文件服务器&#xff0c;有没有更简单且无需后期维护的方案&#xff0c;我喝了一口…

MP2110A Anritsu 安立 采样示波器 眼图设备 简述

MP2110A是一款集成了误码率测试仪&#xff08;BERT&#xff09;和采样示波器的一体化测量仪器&#xff0c;主要用于光学模块的误码率&#xff08;BER&#xff09;测量、眼图分析等评估操作。它支持从10G到800G的光学模块制造过程中的检测分91522。MP2110A内置4通道采样示波器&a…

【InternLM实战营---第七节课笔记】

一、本期课程内容概述 本节课的主讲老师是【曹茂松、刘卓鑫】。教学内容主要包括以下三个部分&#xff1a; 1.大模型评测的背景 2.大模型评测工具OpenCompass的介绍 3.OpenCompass实战 二、学习收获 为什么要研究大模型的评测&#xff1f; 首先&#xff0c;研究评测对于我们全…