Vue项目实践:使用滚动下拉分页优化大数据展示页面【通过防抖加标志位进行方案优化】

Vue项目实践:使用滚动下拉分页优化大数据展示页面

前言

        传统的分页机制通过点击页码来加载更多内容,虽然直观,但在处理大量数据时可能会导致用户体验不佳。相比之下,滚动下拉分页能够在用户滚动到页面底部时自动加载更多内容,既节省了用户操作,也使得数据的展示更加流畅自然。

准备工作

scrollTop,clientHeight,scrollHeight 详解

Vue项目实践:使用滚动下拉分页优化大数据展示页面

  1. scrollTop
    定义:scrollTop 属性表示元素在垂直方向上已经滚动过的距离。换句话说,它衡量的是元素内容顶部与视口顶部之间的距离。这个值通常是非负的,单位是像素。
    应用场景:当你需要知道元素内部滚动了多少或者想要手动设置滚动位置时,会用到这个属性。例如,实现“回到顶部”按钮功能时,可以设置 scrollTop0来瞬间返回顶部。
  2. clientHeight
    定义:clientHeight 表示元素可视区域的高度,即元素内容区的高度加上垂直边框和内边距(padding),但不包括水平滚动条(如果存在)、外边距或滚动条本身。这个值总是正的,单位也是像素。
    应用场景:当你需要计算元素实际显示给用户的高度时会用到 clientHeight,比如判断元素是否完全在视口内显示。
  3. scrollHeight
    定义:scrollHeight 表示元素的总高度,包括不可见的部分,也就是元素内容的总高度,不论内容是否在当前视口内可见。这包括了所有内边距、边框,但不包括外边距。对于没有滚动条的元素,scrollHeight 等于元素的 clientHeight
    应用场景:当你需要了解元素内容的完整高度,特别是用于判断是否还有更多内容可以滚动查看时,scrollHeight 就显得非常重要。比如,结合 scrollTopclientHeight来判断是否已经滚动到底部,从而实现无限滚动加载功能。

实现思路

在实现一个无限滚动(滚动加载更多)功能时,可以通过比较 scrollTop + clientHeightscrollHeight 来判断是否接近滚动底部。

实现

效果

Vue项目实践:使用滚动下拉分页优化大数据展示页面

HTML\CSS结构

注意:一定要设置需要滚动盒子device-content的高度,及其overflow: hidden; overflow-y: auto;样式属性,使其具有滚动。通过handleScroll进行监听父盒子的滚动状态,其中device-box是父盒子中的内容列表。

<a-spin dot :loading="deviceLoading" tip="正在加载...">
  <div class="device-content" @scroll="handleScroll">
    <div v-for="device in deviceList" :key="device.id" class="device-box">
      <div class="device-con-box">
        <div class="device-con-img"></div>
        <div class="device-con-text">
          <div class="device-con-text-top">{{
            device.detectDeviceFullName
          }}</div>
          <div class="device-con-text-bottom">
            <span
              v-if="device.runStatusKey === 'device_run_status:offline'"
              class="offline"
              >离线</span
            >
            <span
              v-if="device.runStatusKey === 'device_run_status:working'"
              class="working"
              >工作</span
            >
            <span
              v-if="device.runStatusKey === 'device_run_status:waiting'"
              class="waiting"
              >空闲</span
            >
            <span
              v-if="device.runStatusKey === 'device_run_status:breakdown'"
              class="breakdown"
              >故障</span
            >
          </div>
        </div>
      </div>
    </div>
  </div>
</a-spin>

CSS结构:

.device-content {
  width: 100%;
  height: 645px;
  overflow: hidden;
  overflow-y: auto;
  .device-box {
    cursor: pointer;
    height: 148px;
    width: 400px;
    float: left;
    border-radius: 12px;
    border: 1px solid #ccc;
    margin-bottom: 6px;
    margin-right: 6px;
    .device-con-box {
      height: 98px;
      width: 305px;
      margin: 0px auto;
      margin: 20px 68px 37px 48px;
      display: flex;
      .device-con-img {
        height: 80px;
        width: 80px;
        background: url('../../assets/images/deviceImg.png');
      }
      .device-con-text {
        width: 220px;
        height: 100%;
        padding-left: 16px;
        .device-con-text-top {
          height: 68px;
          width: 120%;
          padding-top: 23px;
          font-size: 14px;
          font-weight: 400;
          color: #000;
        }
        .device-con-text-bottom {
          height: 30px;
          width: 100%;
          font-family: Microsoft YaHei UI;
          font-size: 24px;
          font-weight: 700;
          line-height: 22px;
          text-align: left;
          color: #19cd61;
        }
        .line-division {
          margin-left: 10px;
          margin-right: 10px;
          color: #e7e7e7;
          font-size: 18px;
          position: relative;
          top: -3px;
        }
      }
    }
  }
}

监听父盒子函数handleScroll

检查用户是否已经滚动到容器的底部,如果滚动到了底部,再次判断页面的数据是否大于总条数,如果小于总条数,则继续进行加载下一页,如果大于总条数,则不进行加载。【距离顶部的距离+可视区高度>=元素总高度

// eslint-disable-next-line no-use-before-define
const handleScroll = (e: Event) => {
  const target = e.target as HTMLElement;
  // 检查用户是否已滚动到容器底部附近
  if (target.scrollTop + target.clientHeight >= target.scrollHeight - 10) {
    // 此条件检查是否还有更多页面的数据需要加载
    if (pagination.current * pagination.pageSize < pagination.total) {
      fetchData({ ...basePagination, current: pagination.current + 1 });
    }
  }
} 

但是会出现,当触底的时候,多次请求分页列表,导致页面存储的数据大于数据库中数据的总条数。

Vue项目实践:使用滚动下拉分页优化大数据展示页面
处理以上触底时多次请求有两种方式可解决

使用防抖技术

使用防抖技术,确保在短时间内只处理一次滚动事件。

// 防抖函数
function debounce(func: any, wait: any) {
  let timeout: number | undefined;

  // eslint-disable-next-line func-names
  return function (...args: any[]) {
    // eslint-disable-next-line @typescript-eslint/no-this-alias
    const context: any = this;

    clearTimeout(timeout);
    timeout = window.setTimeout(() => {
      func.apply(context, args);
    }, wait);
  };
}

添加标志位

添加一个标志位isFetching 来防止在请求完成之前再次发送请求。

const isFetching = ref(false);

const fetchData = async (
  params: PolicyParams = { current: 1, pageSize: 20 }
) => {
  if (isFetching.value) return;
  isFetching.value = true;
  setLoading(true);
  try {
    const { data } = await getDetectDeviceMonitorPage(params);
    pagination.current = params.current;
    pagination.total = data.total;
    if (params.current === 1) {
      deviceList.value = data.data;
    } else {
      deviceList.value = [...deviceList.value, ...data.data];
    }
  } catch (err) {
    // you can report use errorHandler or other
  } finally {
    setLoading(false);
    isFetching.value = false;
  }
};

const handleScroll = (e: Event) => {
  const target = e.target as HTMLElement;
  // 检查用户是否已滚动到容器底部附近
  if (target.scrollTop + target.clientHeight >= target.scrollHeight - 10) {
    // 此条件检查是否还有更多页面的数据需要加载
    if (!isFetching.value && pagination.current * pagination.pageSize < pagination.total) {
      fetchData({ ...basePagination, current: pagination.current + 1 });
    }
  }
};

通过添加防抖和标志位后的效果
Vue项目实践:使用滚动下拉分页优化大数据展示页面
完美解决触底出现多次分页请求。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

C++全栈聊天项目(22) 气泡聊天对话框

气泡聊天框设计 我们期待实现如下绿色的气泡对话框 对于我们自己发出的信息&#xff0c;我们可以实现这样一个网格布局管理 NameLabel用来显示用户的名字&#xff0c;Bubble用来显示聊天信息&#xff0c;Spacer是个弹簧&#xff0c;保证将NameLabel,IconLabel&#xff0c;Bubb…

Android中的Audio系统框架分析(一)

概述 Audio系统是Android 平台重要的组成部分&#xff0c;我们将从以下几个方面来讲解&#xff1a; 一Audio基础知识讲解 二、Android系统中Audio框架 Audio基础知识讲解 我们大家知道声音是由物体振动产生的声波。是通过介质&#xff08;空气或固体、液体&#xff09;传播并…

【C++高阶】C++继承学习手册:全面解析继承的各个方面

&#x1f4dd;个人主页&#x1f339;&#xff1a;Eternity._ ⏩收录专栏⏪&#xff1a;C “ 登神长阶 ” &#x1f921;往期回顾&#x1f921;&#xff1a;模板进阶 &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; 继承 &#x1f4d6;1. 继承的概念及定义…

每日一练——用队列实现栈

225. 用队列实现栈 - 力扣&#xff08;LeetCode&#xff09; Queue.h #pragma once #include<stdlib.h> #include<assert.h> #include<stdbool.h>typedef int QDataType;typedef struct QNode {QDataType data;struct QNode* next; } QNode;typedef struct …

案例 采用Springboot默认的缓存方案Simple在三层架构中完成一个手机验证码生成校验的程序

案例 Cacheable 是 Spring Framework 提供的一个注解&#xff0c;用于在方法执行前先检查缓存&#xff0c;如果缓存中已存在对应的值&#xff0c;则直接返回缓存中的值&#xff0c;而不执行该方法体。如果缓存中不存在对应的值&#xff0c;则执行方法体&#xff0c;并将方法的…

hugo 博客写作流程 (二)

写作工具 推荐两款软件,本人都使用过: typora和obsidian typora: https://github.com/woniu336/typora-007 新建文章 在博客目录找到shell/quickstart.sh双击打开即可 发布到Github 前提: 魔法上网在Github新建一个仓库 找到shell/quickstart.sh双击打开,选择7.SSH 管理…

Android采用Scroller实现底部二楼效果

需求 在移动应用开发中&#xff0c;有时我们希望实现一种特殊的布局效果&#xff0c;即“底部二楼”效果。这个效果类似于在列表底部拖动时出现额外的内容区域&#xff0c;用户可以继续向上拖动查看更多内容。这种效果可以用于展示广告、推荐内容或其他信息。 效果 实现后的…

代理设计模式,框架AOP思想

文章目录 引言&#x1f92a;代理对象(Proxy)如何开发一个代理对象开发中的业务层代码冗余问题开发静态代理类动态代理 引言&#x1f92a; 代理 (proxy) &#xff0c;举个生活中常见的现象&#xff0c;在之前网路还未走进大众的时代里&#xff0c;如果我们想买一些东西&#xf…

Java——构造器(构造方法)和 this

一、什么是构造器 构造器&#xff08;Constructor&#xff09;是Java类的一种特殊方法&#xff0c;用于初始化对象的状态。构造器在创建对象时被调用&#xff0c;可以对对象的成员变量进行初始化。 我之前的文章《Java——类和对象-CSDN博客》中也提到了构造器。 二、构造器…

pc repair

pc repair 修理电脑&#xff0c;换配件

【猫狗分类】Pytorch VGG16 实现猫狗分类1-数据清洗+制作标签文件

Pytorch 猫狗分类 用Pytorch框架&#xff0c;实现分类问题&#xff0c;好像是学习了一些基础知识后的一个小项目阶段&#xff0c;通过这个分类问题&#xff0c;可以知道整个pytorch的工作流程是什么&#xff0c;会了一个分类&#xff0c;那就可以解决其他的分类问题&#xff0…

马斯克在2024年特斯拉股东大会上的年度发言

马斯克表示&#xff0c;“如果市盈率是20或25倍&#xff0c;那就意味着&#xff0c;光是Optimus就能带来20万亿美元的市值。而自动驾驶汽车的市值可能在5到10万亿美元之间。因此&#xff0c;特斯拉的市值达到当今市值最高公司的10倍&#xff0c;是可以想象的&#xff0c;也是有…

一个在C#中集成Python的例子

一个在C#中集成Python的例子。在C#中可以执行Python脚本&#xff0c;在Python中也可以调用C#宿主中的功能&#xff08;clr.AddReference(Business)&#xff09;。 文件说明 Debug为执行目录 Mgr.exe为执行文件 Py\init.py为python初始化脚本 Py\Lib.zip为python需要的模块&…

大数据实训项目(小麦种子)-02、实训项目整体功能介绍与演示

文章目录 前言界面及功能描述实现功能描述技术选型界面展示首页界面功能1&#xff1a;HDFS&#xff0c;选择文件上传文件详细步骤 功能2&#xff1a;MapReduce预处理数据功能3&#xff1a;Hbase存储小麦种子数据并查询前10条记录功能4&#xff1a;Hive分析原始csv文件数据并ech…

【GO-OpenCV】go-cv快速配置

最近对golang实现目标检测心血来潮&#xff0c;尝试在没有sudo权限的平台配置go-cv,有所发现&#xff0c;索性多个平台都做尝试 安装Go语言&#xff08;Golang&#xff09; 通过包管理器安装&#xff08;适用于Debian/Ubuntu&#xff09;(有点慢) 更新包列表&#xff1a; sud…

简单的基于小波变换的图像压缩(Python)

2023 沃尔夫数学奖得主&#xff0c;给了杜克大学的Ingrid Daubechies&#xff08;多贝西&#xff09;教授 以色列沃尔夫基金会理事会成员 Michael Lin 教授在周二宣布: “Ingrid Daubechies is awarded the Wolf Prize for her work in the creation and development of wavel…

搭建k8s集群报错unknown command “\u00a0“ for “kubeadm init“

搭建k8s报错unknown command “\u00a0” for “kubeadm init” 网上搜了一下&#xff0c;是因为复制过来的命令前面包含了空格&#xff0c;将复制的命令放到idea可以清楚看到几个命令前面有空格&#xff0c;删除掉就好了&#xff0c;记录一下

设计模式-享元模式Flyweight(结构型)

享元模式(Flyweight) 享元模式是一种结构型模式&#xff0c;它主要用于减少创建对象的数量&#xff0c;减少内存占用。通过重用现有对象的方式&#xff0c;如果未找到匹配对象则新建对象。线程池、数据库连接池、常量池等池化的思想就是享元模式的一种应用。 图解 角色 享元工…

【团队成长】2024-24周周报-第一次组会人员分工48期推文预告

大家好&#xff01;我们是IndustryOR 团队&#xff0c;致力于分享业界落地的算法技术。欢迎关注微信公众号/知乎/CSDN【运筹匠心】 。 记录人&#xff1a;张哲铭&#xff0c;算法专家&#xff0c;某互联网大厂 【团队成长/个人成长】系列的推文会以 【工作周报】 的方式记录Ind…

【机器学习】人工智能与气候变化:利用深度学习与机器学习算法预测和缓解环境影响

&#x1f4dd;个人主页&#xff1a;哈__ 期待您的关注 目录 &#x1f525;引言 1.1 背景介绍 1.2 人工智能与机器学习的崛起 1.3 本文内容概述 &#x1f528;气候变化的挑战 2.1 现今气候变化带来的影响和挑战 2.2 引发关注的气候变化趋势和数据 &#x1f916;人工智能…