前端reactvue3——实现滚动到底加载数据

news2024/11/30 5:33:56

文章目录

    • ⭐前言
    • ⭐react 实现滚动加载
    • ⭐vue3 实现滚动加载
    • ⭐总结
    • ⭐结束

⭐前言

大家好,我是yma16,本文分享 前端react&vue3——实现滚动加载(到底部加载)
scrollTop 属性

一个双精度浮点值,表示元素当前从原点垂直滚动的像素数,其中正值表示元素向下滚动(以显示更多底部的内容)。如果元素根本没有向上或向下滚动,则 scrollTop 为 0。如果文档不是活动文档,则返回值为 0。如果文档在亚像素精度设备上呈现,则返回的值也是亚像素精度的,可能包含小数部分。

clientHeight 属性

只读属性 Element.clientHeight 对于没有定义 CSS 或者内联布局盒子的元素为 0;否则,它是元素内部的高度(以像素为单位),包含内边距,但不包括边框、外边距和水平滚动条(如果存在)。
clientHeight 可以通过 CSS height + CSS padding - 水平滚动条高度(如果存在)来计算。

scrollHeight 属性

scrollHeight 只读属性是一个元素内容高度的度量,包括由于溢出导致的视图中不可见内容

node系列往期文章
node_windows环境变量配置
node_npm发布包
linux_配置node
node_nvm安装配置
node笔记_http服务搭建(渲染html、json)
node笔记_读文件
node笔记_写文件
node笔记_连接mysql实现crud
node笔记_formidable实现前后端联调的文件上传
node笔记_koa框架介绍
node_koa路由
node_生成目录
node_读写excel
node笔记_读取目录的文件
node笔记——调用免费qq的smtp发送html格式邮箱
node实战——搭建带swagger接口文档的后端koa项目(node后端就业储备知识)
node实战——后端koa结合jwt连接mysql实现权限登录(node后端就业储备知识)
node实战——koa给邮件发送验证码并缓存到redis服务(node后端储备知识)

koa系列项目文章
前端vite+vue3结合后端node+koa——实现代码模板展示平台(支持模糊搜索+分页查询)
node+vue3+mysql前后分离开发范式——实现对数据库表的增删改查
node+vue3+mysql前后分离开发范式——实现视频文件上传并渲染

koa-vue性能监控到封装sdk系列文章
性能监控系统搭建——node_koa实现性能监控数据上报(第一章)
性能监控系统搭建——vue3实现性能监控数据展示(第二章)
性能监控计算——封装带性能计算并上报的npm包(第三章)
canvas系列文章
web canvas系列——快速入门上手绘制二维空间点、线、面
webgl canvas系列——快速加背景、抠图、加水印并下载图片
webgl canvas系列——animation中基本旋转、平移、缩放(模拟冒泡排序过程)

⭐react 实现滚动加载

判断滚动到底部:Math.ceil(scrollTop+clientHeight+1)>= scrollHeight
这里+1和向上取整是考虑到scrollTop是浮点数
react demo 案例:

import { useEffect, useRef, useState, useCallback } from 'react';
import {Button,notification} from 'tdesign-react'

const ScrollDemo=(props:any,ref:any)=> {
  // @ts-ignore 列表数据
  const [listData,setListData]=useState<any>([])
  // ref
  const scrollRef=useRef<HTMLElement|any>(null);
  // 初始化数据
  const initData=()=>{
    const data=[];
    for(let i=1;i<50;++i){
      data.push({
        label:`label${i}`,
        value:`label${i}`,
      })
    }
    return data
  };
  // 重置
  const resetData=()=>{
    setListData(initData())
  };

  //追加数据
  const appendData=useCallback(()=>{
    const data=[];
    const length=listData.length
    for(let i=length+1;i<10+length;++i){
      data.push({
        label:`label${i}`,
        value:`label${i}`,
      })
    }
    setListData(listData.concat(data))
  },[listData])
  //滚动事件
  const scrollEvent=(e:any)=>{
    console.log('e',e)
    // 不使用滚动条的情况下为了适应视口中所用内容所需的最小高度
    const scrollHeight=e.target.scrollHeight
    // 从其顶部边缘滚动的像素数
    const scrollTop=e.target.scrollTop
    // dom 视口高度(不包含任何滚动条)
    const clientHeight=e.target.clientHeight
    console.log('scrollTop',scrollTop)
    console.log('clientHeight',clientHeight)
    console.log('scrollHeight',scrollHeight)
    // 向上取整
    if(Math.ceil(scrollTop+clientHeight+1)>= scrollHeight ){
      notification.info({
        title: '到底啦!',
      })
      appendData()
    }
  }
  //监听 dom滚动
  const listenDomScroll=()=>{
    try{
      if(scrollRef.current){
        //@ts-ignore
        scrollRef.current.removeEventListener('scroll',scrollEvent)
        scrollRef.current.addEventListener('scroll',scrollEvent)
      }
    }
    catch (e) {
      console.error(e)
    }
  };

  //  初始化
  useEffect(()=>{
    resetData()
  },[])
  // 数据变化重新监听dom
  useEffect(()=>{
    if(scrollRef.current){
      listenDomScroll()
    }
  },[scrollRef,listData])
  return <div style={{padding:'10px',textAlign:'left'}}>
<Button onClick={resetData} style={{margin:'10px'}}>
  重置
</Button>

    <div>
      <div style={{maxHeight:'300px',width:'200px',overflowY:'auto',}} ref={scrollRef}>
        {listData.map((item:any)=>{
          return <div key={item.value} style={{background:'#0052d9',color:'#fff',margin:'2px',padding:'2px'}}>{item.label}</div>
        })}
      </div>
    </div>

    </div>
};
export default ScrollDemo

效果:
react-scroll-demo

⭐vue3 实现滚动加载

vue3 demo 实例:

<script setup lang="ts">
import { ref, reactive, onMounted } from 'vue'
import { notification } from 'ant-design-vue'
const scrollRef = ref()
type ListDataType = { label: string, value: string }
// 初始化数据
const initData = (): ListDataType[] => {
    const data: ListDataType[] = [];
    for (let i = 1; i < 50; ++i) {
        data.push({
            label: `label${i}`,
            value: `label${i}`,
        })
    }
    return data
};
// state 
const state: any = reactive({
    listData: initData()
})

// 重置
const resetData = () => {
    state.listData = initData()
};

//追加数据
const appendData = () => {
    const data: any = [];
    const length = state.listData.length
    for (let i = length + 1; i < 10 + length; ++i) {
        data.push({
            label: `label${i}`,
            value: `label${i}`,
        })
    }
    state.listData = [...state.listData, ...data]
}
//滚动事件
const scrollEvent = (e: any) => {
    console.log('e', e)
    // 不使用滚动条的情况下为了适应视口中所用内容所需的最小高度
    const scrollHeight = e.target.scrollHeight
    // 从其顶部边缘滚动的像素数
    const scrollTop = e.target.scrollTop
    // dom 视口高度(不包含任何滚动条)
    const clientHeight = e.target.clientHeight
    console.log('scrollTop', scrollTop)
    console.log('clientHeight', clientHeight)
    console.log('scrollHeight', scrollHeight)
    // 向上取整
    if (Math.ceil(scrollTop + clientHeight + 1) >= scrollHeight) {
        notification.open({
            message: '到底啦!',
        })
        appendData()
    }
}
//监听 dom滚动
const listenDomScroll = () => {
    try {
        if (scrollRef.value) {
            //@ts-ignore
            scrollRef.value.removeEventListener('scroll', scrollEvent)
            scrollRef.value.addEventListener('scroll', scrollEvent)
        }
    }
    catch (e) {
        console.error(e)
    }
};


// 初始化页面
onMounted(() => {
    listenDomScroll()
})

</script>
<template>
    <div>
        <a-button type="primary" @click="resetData">重置</a-button>
        <div style="max-height:300px;overflow-y:auto;width:200px" ref="scrollRef">
            <div v-for="item in state.listData" :key="item.value"
                style="background:#0052d9;color:#fff;padding:2px;margin:2px;">
                {{ item.label }}
            </div>
        </div>
    </div>
</template>

效果:
vue-scroll-demo
代码块inscode

⭐总结

底部加载的关键判断条件是:Math.ceil(scrollTop + clientHeight + 1) >= scrollHeight。

在使用react时,需要注意通过dom监听数据的变化。而在使用vue3时,数据具有响应式特性,因此只需在滚动加载时添加数据即可。

⭐结束

本文分享到这结束,如有错误或者不足之处欢迎指出!
在这里插入图片描述

👍 点赞,是我创作的动力!

⭐️ 收藏,是我努力的方向!

✏️ 评论,是我进步的财富!

💖 最后,感谢你的阅读!

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

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

相关文章

全国41G带高度的矢量建筑楼块

建筑数据用于精确描述建筑物的空间位置和范围&#xff0c;支持城市规划、灾害管理、房地产开发及各类空间分析等多领域应用。 数据介绍 带有高度的建筑数据在气候建模、能耗分析及社会经济活动等多种应用中起着至关重要的作用。 尽管这些信息至关重要&#xff0c;但以往的研…

入门必备:什么是鸿蒙系统

鸿蒙系统(HarmonyOS)是华为公司发布的一款基于微内核的面向全场景的分布式操作系统。以下是对它的具体介绍&#xff1a; 1. 核心特点: • 分布式能力&#xff1a;这是鸿蒙系统的核心优势之一。它能够将多种不同类型的智能终端设备连接起来&#xff0c;使这些设备在系统层面相…

MySQL数据的导出

【图书推荐】《MySQL 9从入门到性能优化&#xff08;视频教学版&#xff09;》-CSDN博客 《MySQL 9从入门到性能优化&#xff08;视频教学版&#xff09;&#xff08;数据库技术丛书&#xff09;》(王英英)【摘要 书评 试读】- 京东图书 (jd.com) MySQL9数据库技术_夏天又到了…

MySQL中什么情况下类型转换会导致索引失效

文章目录 1. 问题引入2. 准备工作3. 案例分析3.1 正常情况3.2 发生了隐式类型转换的情况 4. MySQL隐式类型转换的规则4.1 案例引入4.2 MySQL 中隐式类型转换的规则4.3 验证 MySQL 隐式类型转换的规则 5. 总结 如果对 MySQL 索引不了解&#xff0c;可以看一下我的另一篇博文&…

Hadoop集群安装

集群规划 node01node02node03角色主节点从节点从节点NameNode√DataNode√√√ResourceManager√NodeManager√√√SecondaryNameNode√Historyserver√ 上传安装包到node01 解压到指定目录 tar -zxvf /bigdata/soft/hadoop-3.3.3.tar.gz -C /bigdata/server/ 创建软链接 cd…

在线matlab环境

登陆https://ww2.mathworks.cn/ 在线文档https://ww2.mathworks.cn/help/index.html 在线环境[需要先登陆]

C4T避风型电动采光排烟天窗(图集09J621-2)

C4T避风型电动采光排烟天窗是09J621-2《电动采光排烟天窗》图集中的一种窗型。也是一种现代化的建筑消防排烟通风采光设备&#xff0c;被广泛应用于多风地区厂房。 C4T避风型电动采光排烟天窗配有成品避风罩&#xff0c;该避风置由钢制骨架和彩色钢板构成&#xff0c;固定在电动…

50 | 装饰器模式:通过剖析Java IO类库源码学习装饰器模式

上一篇文章我们学习了桥接模式&#xff0c;桥接模式有两种理解方式。第一种理解方式是“将抽象和实现解耦&#xff0c;让它们能独立开发”。这种理解方式比较特别&#xff0c;应用场景也不多。另一种理解方式更加简单&#xff0c;类似“组合优于继承”设计原则&#xff0c;这种…

openEuler、Linux操作系统常见操作-(6)如何登录Linux

如何登录Linux Linux登陆方式主要有如下两种: 。本地登陆 。一个典型的Linux系统将运行六个虚拟控制台和一个图形控制台&#xff0c;openEuler目前暂未支持图形化界面; 可以通过CtrlAltF[1-6]在6个虚拟控制台之间进行切换。 远程登录 。默认情况下openEuler支持远程登录&…

制作PPT的入门步骤有哪些?2个高效软件轻松搞定PPT!

对于现代的职场人士和学生来说&#xff0c;PPT——PowerPoint已经成为他们工作和学习无法避开的部分&#xff0c;换到各种商业会议、学术报告和教学中&#xff0c;PPT演示文稿都扮演着重要的角色&#xff1a;不仅能够帮助演讲者更好地展示讲义内容&#xff0c;更让观众能够通过…

JavaScript全面指南(四)

​&#x1f308;个人主页&#xff1a;前端青山 &#x1f525;系列专栏&#xff1a;JavaScript篇 &#x1f516;人终将被年少不可得之物困其一生 依旧青山,本期给大家带来JavaScript篇专栏内容:JavaScript全面指南 目录 61、如何防止XSRF攻击 62、如何判断一个对象是否为数组&…

科研绘图系列:R语言散点相关系数图(scatter plot)

文章目录 介绍加载R包数据函数画图系统信息介绍 散点相关系数图是一种数据可视化图表,它结合了散点图和相关系数来展示两个连续变量之间的关系。这种图表通常用于相关性分析,以判断两个变量之间是否存在某种关联,并总结坐标点的分布模式。 在散点相关系数图中,横轴和纵轴…

SpringBoot+Vue+Uniapp智能社区服务小程序系统(源码+lw+部署文档+讲解等)

项目运行截图 技术框架 后端采用SpringBoot框架 Spring Boot 是一个用于快速开发基于 Spring 框架的应用程序的开源框架。它采用约定大于配置的理念&#xff0c;提供了一套默认的配置&#xff0c;让开发者可以更专注于业务逻辑而不是配置文件。Spring Boot 通过自动化配置和约…

截图贴图工具 | PixPin v1.9.0 绿色版

PixPin是一款功能强大且使用简单的截图和贴图工具&#xff0c;它旨在帮助用户提高工作效率。PixPin的主要功能包括截图、贴图、标注、文本识别、长截图和截动图。它允许用户自由选择或自动探测窗口来设定截图范围&#xff0c;精准截取所需内容&#xff0c;并将所截取的图像“贴…

D37【python 接口自动化学习】- python基础之函数

day37 函数的参数 学习日期&#xff1a;20241014 学习目标&#xff1a;输入输出与文件操作&#xfe63;-50 函数的参数&#xff1a;怎样实现函数与外部数据通信&#xff1f; 学习笔记&#xff1a; 实参与形参 代码实现 # 实参与形参 def foo(number):print(number)n1123 n…

redis与springBoot整合

前提 要实现,使用Redis存储登录状态 需要一个完整的前端后端的项目 前端项目搭建 解压脚手架 安装依赖 配置请求代理 选做: 禁用EsLint语法检查 Vue Admin Template关闭eslint校验&#xff0c;lintOnSave&#xff1a;false设置无效解决办法_lintonsave: false-CSDN博客 …

【前端】如何制作一个简单的网页(3)

接下来我们为html元素添加网页内容。网页内容按照功能的不同可以区分为网页头与网页体两个部分。 先来说说什么是网页头。 网页头 网页头&#xff08;又称为网页头部信息&#xff09;向浏览器提供文档的一些信息。 这些信息包括网页的名称、编码方式、样式、JS代码等。 &…

java项目之纺织品企业财务管理系统源码(springboot+vue+mysql)

风定落花生&#xff0c;歌声逐流水&#xff0c;大家好我是风歌&#xff0c;混迹在java圈的辛苦码农。今天要和大家聊的是一款基于springboot的纺织品企业财务管理系统。项目源码以及部署相关请联系风歌&#xff0c;文末附上联系信息 。 项目简介&#xff1a; 基于spring boot…

Thread类的基本用用法

1.创建线程 1.1继承Thread类 线程创建需要Thread类但是不需要import导入是为什么&#xff1f; 因为java.lang默认import不需要导入&#xff0c;java.lang中包含Thread 为什么在MyThread类中只能使用try catch 无法使用throws&#xff1f; 因为父类Thread run中没有throws …

Java 日志打印

使用日志打印&#xff1a; private static Logger log LoggerFactory.getLogger(DeptController.class);RequestMapping("/depts")public Result list() { // System.out.println("查询全部部门数据");log.info("查询全部部门数据");ret…