React中使用LazyBuilder实现页面懒加载方法二

前言:

        在一个表格中,需要展示100条数据,当每条数据里面需要承载的内容很多,需要渲染的元素也很多的时候,容易造成页面加载的速度很慢,不能给用户提供很好的体验时,懒加载是优化页面加载速度的方法之一。

策略:
        前端在接受到api返回的数据的时候,可以先根据数据总的条数进行遍历,给每一项初始化简单的dom进行渲染占位,通过IntersectionObserver对每一项元素进行监听,当初始dom出现在页面视口的时候,需要替换掉初始dom,渲染真实dom。这样可以实现:在初始dom出现在视口内时,替换掉初始dom,渲染真实dom,并取消对该dom的监听,实现只需加载一次,首次加载多少个真实dom,取决于可视区域跟初始dom的高度

React中使用LazyBuilder实现页面懒加载方法一

与方法一不同之处:

方法一:元素出现在可视区域内,即渲染真实dom,一旦消失在可视区域内,即渲染初始dom

方法二:元素只要出现在可视区域内一次,即渲染真实dom,并且取消对该dom的监听,只需加载一次

LazyBuilder.jsx
import React, { Component, createRef } from "react";
class LazyBuilder extends Component {static defaultProps = {initComponent: null,initHeight: null,controller: null,className: null,style: null,}/*** @param {Object} props* @param {JSX.Element} [props.initComponent] - 默认组件* @param {Number} [props.initHeight] - 组件高度* @param {LazyController} [props.controller] - LazyController*/constructor(props) {super(props);this._ref = createRef();this.controller = this.props.controller instanceof LazyController ? this.props.controller : new LazyController();this.state = {isLoading: true,initStyle: {width: "100%",height: props.initHeight},key: `lazy_${Math.random().toString(16).slice(2)}`,}}componentDidMount() {// 页面初始化时,对所有元素进行绑定监听this.controller.observe(this._ref.current, this.updateShowElement.bind(this));}// 组件销毁时componentWillUnmount() {const { autoDispose } = this.props;if (autoDispose && this.controller.size() === 0) {this.controller.dispose();return;}this.controller.unobserve(this._ref.current);}updateShowElement = () => {// 元素出现在视口以内this.setState({isLoading: false,initStyle: null,});}render () {const { children, initComponent } = this.props;const { isLoading, initStyle } = this.state;const className = ["lazy-builder-item", this.props.className].filter(item => typeof item === "string").join("\s");return (<div id={this.state.key} ref={this._ref} className={className} style={Object.assign({}, initStyle, this.props.style)}>{isLoading ? initComponent : children}</div>);}
}class LazyController {constructor(){// 定义map来存储所有的dom项this._map = new Map();// IntersectionObserver 对每一项元素进行监听this.observer = new IntersectionObserver((entries) => {for (const entry of entries) {// isIntersecting: true - 出现在视口    false - 隐藏(视口以外)if (entry.isIntersecting) {const updateShowElement = this._map.get(entry.target);if (typeof updateShowElement === "function") {updateShowElement()}this.unobserve(entry.target);}}});}// 观察指定DOMobserve = (target, callback) => {if (this.observer && !this.has(target)) {this._map.set(target, callback);this.observer.observe(target);}}// 取消对指定DOM的观察unobserve = (target) => {if (this.observer && this.has(target)) {this.observer.unobserve(target);this._map.delete(target);}}// 判断一个DOM是否正在被观察has = (target) => {return this._map.has(target);}// 返回正在观测中的DOM数量size = () => {return this._map.size();}// 停止对所有DOM的观测并销毁IntersectionObserver实例dispose = () => {if (this.observer == null) {throw new Error("observer未初始化");}this._map.clear();this.observer.disconnect();this.observer = null;}
}export {LazyBuilder,LazyController,
}

Cp.jsx

export default class  Cp extends Component {constructor(props){super(props)// 创建controllerthis.controller = new LazyController();this.state = {// 模拟数据dataList: new Array(100).fill().map((item, index) => index + 1)}}componentWillUnmount() {this.controller.dispose();}render(){const {dataList} = this.statereturn (<div>{Array.isArray(dataList) && dataList.length > 0? dataList.map((item, index) => {return <LazyBuilder key={index}initHeight={200} // 初始dom高度controller={this.controller} // controller><div style={{width: '100%', height: '200px'}}>{`第${item}个元素`}</div></LazyBuilder>}): null}</div>)}
}

初次加载:

滚动后:

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

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

相关文章

springboot 优雅使用函数式编程处理 websocket @OnMessage 消息

背景 现在大多业务功能使用 socket.io实现长连接&#xff0c;但是部分第三方设备对接 只支持基础的websocket。 spring中使用基础的websocket, OnMessage 收到消息&#xff0c;对消息的处理&#xff0c;if else 将会繁琐&#xff0c;难以维护。 本文仅介绍了如何使用enum枚举、…

yarn的安装

下载node.js&#xff0c;使用npm安装 #先加载本地安装 yarn install --offline//安装 npm install -g yarn yarn --version //查看版本 npm install -g yarn //安装安装node.js,下载yarn的安装程序: Yarn 淘宝源安装&#xff0c;分别复制粘贴以下代码行到黑窗口运行即可 …

考研机试 谁是你潜在的朋友

描述 “臭味相投”——这是我们描述朋友时喜欢用的词汇。两个人是朋友通常意味着他们存在着许多共同的兴趣。然而作为一个宅男&#xff0c;你发现自己与他人相互了解的机会并不太多。幸运的是&#xff0c;你意外得到了一份北大图书馆的图书借阅记录&#xff0c;于是你挑灯熬夜地…

Selenium wait element点击

场景&#xff1a;input单元格输入mail格式的字符串&#xff08;会进行字符串mail格式的校验&#xff09;&#xff0c;很快下方的button<next>才变绿可点击。 隐式等待&#xff1a;implicitly_wait method1: 点不上&#xff0c;这里有个坑&#xff0c;下面2种方式不能同时…

插槽(64-67)

文章目录 插槽1.插槽 - 默认插槽(组件内可以定制一处结构)2.插槽 - 后备内容&#xff08;默认值&#xff09;3.插槽 - 具名插槽(组件内可以定制多处结构)4.作用域插槽(插槽的一个传参语法) 插槽 插槽分类:默认插槽和具名插槽 1.插槽 - 默认插槽(组件内可以定制一处结构) 作用…

qt学习:http+访问百度智能云api实现动物图片识别

目录 获取id key 编程步骤 配置ui界面 添加模块,头文件和定义变量 新建两个类,一个图像Image类,一个Http类,http类继承QObject类,并添加头文件并定义成员和函数 实现图像Image类,Http类的函数 在ui界面的cpp中添加全局变量,根据自己的应用来写,开头有获取方法

Java解决ReabbitMQ解决消息重复消费问题

RabbitMQ中解决消息重复消费的问题通常涉及到确保消息的幂等性和使用消息确认机制。以下是一些常见的解决方法&#xff1a; 消息去重&#xff1a;在消费者端实现消息的去重逻辑&#xff0c;例如使用数据库的唯一约束或者分布式锁来保证同一消息不会被处理多次。 消息确认&…

【投稿优惠|EI优质会议】2024年材料化学与清洁能源国际学术会议(IACMCCE 2024)

【投稿优惠|优质会议】2024年材料化学与清洁能源国际学术会议(IACMCCE 2024) 2024 International Conference Environmental Engineering and Mechatronics Integration(ICEEMI 2024) 一、【会议简介】 随着全球能源需求的不断增长&#xff0c;清洁能源的研究与应用成为了国际…

【npm包】如何发布自己的npm包

随着Node.js的普及&#xff0c;npm&#xff08;Node Package Manager&#xff09;已成为JavaScript开发者中不可或缺的一部分。发布自己的npm包&#xff0c;不仅可以将自己的项目分享给更多人&#xff0c;还可以为社区做出贡献。本文将详细介绍如何从零开始发布自己的npm包。 …

【JavaEE Spring】MyBatis 操作数据库 - 进阶

MyBatis 操作数据库 - 进阶 1. 动态SQL1.1 \<if>标签1.2 \<trim>标签1.3 \<where>标签1.4 \<set>标签1.5 \<foreach>标签1.6 \<include>标签 1. 动态SQL 动态 SQL 是Mybatis的强⼤特性之⼀&#xff0c;能够完成不同条件下不同的 sql 拼接…

想找一个轻量版的MarkDown编辑器客户端,哪位推荐一下

经常需要即时写一些MarkDown文档&#xff0c;打开网页版的笔记不方便。 对比了几个&#xff0c;已收费的typora感觉还是最好的。 除此之外&#xff0c;原以为最重的VSCode&#xff0c;从打开速度、占内存等情况来说&#xff0c;居然也不相上下。 这样的对比条件下&#xff0c;…

某赛通电子文档安全管理系统 hiddenWatermark/uploadFile 文件上传漏洞复现

0x01 产品简介 某赛通电子文档安全管理系统(简称:CDG)是一款电子文档安全加密软件,该系统利用驱动层透明加密技术,通过对电子文档的加密保护,防止内部员工泄密和外部人员非法窃取企业核心重要数据资产,对电子文档进行全生命周期防护,系统具有透明加密、主动加密、智能…

常用命令-

Linux服务器命令 scp -P 1122 expdp_aram_prod230903_* root193.8.1.7:/oracle/app/oracle/move_data //跨服务器传输 chown -R oracle:oinstall /app/move_data //更改所属组 date -s 2022-11-11 18:58:30 //修改服务器时间 top //CPU使用率 df -h //磁盘…

趋势也有大小之分?现货白银趋势的简单介绍

在现货白银市场中要做顺势交易&#xff0c;首先要分析趋势&#xff0c;在这一步很多投资者懵逼了&#xff0c;因为有时他们搞不清当前趋势是什么&#xff0c;看起来像下跌&#xff0c;但又像上涨。其实这可能是投资者没搞清楚大趋势和小趋势的关系问题&#xff0c;下面我们就来…

数据结构——链表的实现(Java版)

目录 一、链表 二、代码实现 1.创建结点 2.构造函数 3.链表的相关属性 4.添加虚拟节点 5.判断链表是否为空 6.添加方法 &#xff08;1&#xff09;在头部添加 &#xff08;2&#xff09;在尾部添加 &#xff08;3&#xff09;在索引位置添加 &#xff08;4&#xff…

华为云OBS-文件上传

前端配合后端 采用临时上传 相关参考文档 使用临时URL进行授权访问_对象存储服务 OBS_BrowserJS_临时授权访问_华为云 选择文件方法 【 isPay 是否上传完毕】 handleChange(file, fileList) {this.active 0;this.json_data [];console.log(file, fileList);fileList.forEa…

LiveGBS流媒体平台GB/T28181常见问题-如何配置使用自己已有的redis服务替换redis版本升级redis版本

LiveGBS如何配置使用自己已有的redis服务替换redis版本升级redis版本 1、Redis服务2、如何切换REDIS?2.1、停止启动REDIS2.2、配置信令服务2.3、配置流媒体服务2.4、启动 3、搭建GB28181视频直播平台 1、Redis服务 在LivGBS中Redis作为数据交换、数据订阅、数据发布的高速缓存…

Java二分查找-图文

一、二分查找概念 二分查找也叫折半查找&#xff0c;是在一组有序(升序/降序)的数据中查找一个元素&#xff0c;它是一种效率较高的查找方。 二、二分查找原理 1.二分查找的数组必须是有序数值型数组。 2.将想要查找的目标元素与查找范围内的中间元素进行比较&#xff0c;如果…

数据结构篇-01:单调栈

单调栈是栈的一种&#xff0c;可以使得每次新元素入栈后&#xff0c;栈内的元素都保持有序&#xff08;单调递增或者单调递减&#xff09;。 单调栈的用途不太广泛&#xff0c;只处理一类典型的问题&#xff0c;比如[下一个更大元素]、[上一个更小元素] 等。 在本文中&#x…

Pandas应用-股票分析实战

股票时间序列 时间序列&#xff1a; 金融领域最重要的数据类型之一 股价、汇率为常见的时间序列数据 趋势分析&#xff1a; 主要分析时间序列在某一方向上持续运动 在量化交易领域&#xff0c;我们通过统计手段对投资品的收益率进行时间序列建模&#xff0c;以此来预测未来的收…