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

news2024/12/4 17:03:05

前言:

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

策略:

        前端在接受到api返回的数据的时候,可以先根据数据总的条数进行遍历,给每一项初始化简单的dom进行渲染占位,通过IntersectionObserver对每一项元素进行监听,当初始dom出现在页面视口的时候,需要替换掉初始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: undefined,
        firstIsLoading: true, // 作用:在页面进行初始渲染时,所有的项都设置初始dom
        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));
  }

  updateShowElement = (type) => {
    const {initHeight} = this.props
    if(type == 1){
      // 元素出现在视口以内
      this.setState({
        isLoading: false,
        firstIsLoading: false,
        initStyle: null,
      });
    } else if(type == 2) {
      // 元素出现在视口以外
      this.setState({
        isLoading: true,
        initStyle: {
          width: "100%",
          height: initHeight
        },
      });
    }
  }

  render () {
    const { children, initComponent } = this.props;
    const { isLoading, initStyle, firstIsLoading} = 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)}>
          {
            firstIsLoading
            ? initComponent
            : isLoading ? initComponent : children
          }
        </div>
    );
  }
}

class LazyController {
  constructor(){

    // 定义map来存储所有的dom项
    this._map = new Map();

    // IntersectionObserver 对每一项元素进行监听
    this.observer = new IntersectionObserver((entries) => {
      for (const entry of entries) {
        const updateShowElement = this._map.get(entry.target);
        // isIntersecting: true - 出现在视口    false - 隐藏(视口以外)
        if (entry.isIntersecting) {
          if (typeof updateShowElement === "function") {
            updateShowElement(1)
          }
        } else {
          if (typeof updateShowElement === "function") {
            updateShowElement(2)
          }
        }
      }
    });
  }

  // 观察指定DOM
  observe = (target, callback) => {
    if (this.observer && !this.has(target)) {
      // 初始化时,将每一项保存在map中
      this._map.set(target, callback);
      this.observer.observe(target);
    }
  }

  // 判断一个DOM是否正在被观察
  has = (target) => {
    return this._map.has(target);
  }

}

export {
  LazyBuilder,
  LazyController,
}

cp.jsx

import React, {Component} from 'react';
import { LazyBuilder, LazyController } from './LazyBuilder'
export default class  Cp extends Component {
  constructor(props){
    super(props)

    // 创建controller
    this.controller = new LazyController();
    this.state = {
      // 模拟数据
      dataList: new Array(100).fill().map((item, index) => index + 1)
    }
  }

  render(){
    const {dataList} = this.state
    return (
      <div>
        {
          Array.isArray(dataList) && dataList.length > 0
          ? dataList.map((item, index) => {
            return <LazyBuilder 
                    key={index}
                    initHeight={100} // 初始dom高度
                    controller={this.controller} // controller
                  >
                    <div style={{width: '100%', height: '200px'}}>{`第${item}个元素`}</div>
                  </LazyBuilder>
          })
          : null
        }
      </div>
    )
  }
}

效果

页面刚加载时,只有前面几条数据在视口内 

经过滚动后

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

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

相关文章

[Linux基础开发工具---vim]关于vim的介绍、vim如何配置及vim的基本操作方法

一、vim及其三种模式的简单介绍 Vim是一个类似于Vi的文本编辑器&#xff0c;不同的是vim是vi的升级版本&#xff0c;它不仅兼容vi的所有指令&#xff0c;而且还有一些新的特性在里面,如多级撤销、多窗口操作、崩溃后也可以恢复、增加了稳定性、关键字自动补全、上下文自动补全等…

如何使用 WebRTC 与 Kurento 建立视频会议 App

本文作者 WebRTC Ventures 工程师。在 RTC 2018 实时互联网大会上&#xff0c;WebRTC Ventures 的资深软件工程师&#xff0c;将围绕 WebRTC 开发带来经验分享。欢迎访问RTC 开发者社区&#xff0c;与更多WebRTC开发者交流经验。 了解 WebRTC 如何工作的一种简单方式是通过学习…

SpringBoot的默认组件扫描

本篇博客主要探究&#xff1a;为什么SpringBoot项目中我们没有配置组件扫描的包&#xff0c;为什么它会默认扫描启动类所在的包&#xff1f; 一、访问与启动类所在同一包下的接口 我们先来看一个简单的接口&#xff1a; 我们可以观察到&#xff0c;HelloController这个类处在…

如何做接口测试?看完这个图让你清楚了解接口测试

01 通用的项目架构 02 什么是接口 接口&#xff1a;服务端程序对外提供的一种统一的访问方式&#xff0c;通常采用HTTP协议&#xff0c;通过不同的url&#xff0c;不同的请求类型&#xff08;GET、POST&#xff09;&#xff0c;不同的参数&#xff0c;来执行不同的业务逻辑…

大数据学习之Redis、从零基础到入门(二)

二、Redis安装配置 1. VMWare本地虚拟机 VMWare准备的为64位 查看自己的VMWare是32位还是64位 getconf LONG_BIT 2. Redis的安装 2.1 系统选择 选择Linux系统 2.2 Linux版安装 2.2.1 Linux环境安装Redis必须先具备gcc编译环境 ①什么是gcc gcc是linux下的一个编译程序&…

应急响应-Windows-进程排查

进程&#xff08;process&#xff09;是计算机中的程序关于某数据集合上的一次运动活动&#xff0c;是系统进行资源分配和调度的基本单位&#xff0c;是操作系统结果的基础。在早期面向进程结构中&#xff0c;进程是线程的容器。无论是在Windows系统还是Linux系统中&#xff0c…

Vue 3.0中Treeshaking特性(详细解析)

文章目录 一、是什么二、如何做Vue2 项目Vue3 项目 三、作用参考文献 一、是什么 Tree shaking 是一种通过清除多余代码方式来优化项目打包体积的技术&#xff0c;专业术语叫 Dead code elimination 简单来讲&#xff0c;就是在保持代码运行结果不变的前提下&#xff0c;去除…

vue项目中如何使用SVG图标

IconFont使用的不足&#xff1a;图标添加、修改、删除以后在线链接需要更新离线资源需要重新下载项目代码需要同步更新。 在项目不断更新和迭代的过程中&#xff0c;图标的增减变化还没有稳定的情况下&#xff0c;开发人员的工作效率会明显下降。 那么有没有一个图标应用方式…

利用大数据靶向肿瘤细胞的基因突变

在亚利桑那健康科学大学&#xff0c;研究人员正在应用大量数据&#xff0c;试图更多地了解这种突变、其变异以及任何可能有助于他们治疗患者的相关因素。 癌症的潜在原因很多&#xff0c;从食物和环境到创伤和感染。在遗传学方面&#xff0c;研究人员发现&#xff0c;有一种基因…

Unity中实现合理塔防寻路机制

前言 在一款TD游戏中,最重要的单位就两大类:防御塔(Tower)和敌人单位(Enemy)。在处理敌人单位的AI行为时,最基本也是最重要的就是自动寻路。在各式TD游戏中,防御塔的攻击方式以及敌人单位的Buff机制往往是能做出差异化的地方;而在寻路问题上,几乎是没有差异的,面对…

Springboot注解@Aspect(一)之@Aspect 作用和Aop关系详解

目录 Aspect的使用 配置 作用 通知相关的注解 例子 结果&#xff1a; Aspect作用和Spring Aop关系 示例 标签表达式 Aspect的使用 配置 要启用 Spring AOP 和 Aspect 注解&#xff0c;需要在 Spring 配置中启用 AspectJ 自动代理&#xff0c;但是在 Spring Boot 中&a…

shell脚本-函数及数组

一.函数 1.函数的作用 语句块定义成函数约等于别名&#xff0c;定义函数&#xff0c;再引用函数 封装的可重复利用的具有特定功能的代码 2.函数的基本格式 法一&#xff1a; [function] 函数名 {命令序列[return x] #使用return或者exit可以显式的结束函数 }法二&…

对比一下Confluence,其实HelpLook搭建知识库也不错

随着越来越多的企业转向远程工作和分散团队&#xff0c;寻找一种适合团队协作和知识共享的工具变得更为重要。HelpLook和Confluence是两个我认为比较相似的知识库软件&#xff0c;它们都提供了丰富的功能和卓越的用户体验。接下来就对HelpLook和Confluence进行详细的介绍和对比…

【Spring 篇】MyBatis DAO层实现:数据之舞的精灵

欢迎来到MyBatis DAO层的神奇世界&#xff0c;这里将为你揭示DAO层的奥秘&#xff0c;让你成为数据之舞的精灵。无论你是初学者还是想要深入了解DAO层的开发者&#xff0c;这篇博客将引导你踏入MyBatis DAO层的王国&#xff0c;一探其中的精彩。 舞台1&#xff1a;DAO层的角色…

【大数据面试题】HBase面试题附答案

目录 1.介绍下HBase 2.HBase优缺点 3.介绍下的HBase的架构 4.HBase的读写缓存 5.在删除HBase中的一个数据的时候&#xff0c;它是立马就把数据删除掉了吗? 6.HBase中的二级索引 7.HBase的RegionServer宕机以后怎么恢复的? 8.HBase的一个region由哪些东西组成? 9.…

安科瑞电化学储能电能管理系统解决方案——安科瑞赵嘉敏

1 概述 在我国新型电力系统中&#xff0c;新能源装机容量逐年提高&#xff0c;但是新能源比如光伏发电、风力发电是不稳定的能源&#xff0c;所以要维持电网稳定&#xff0c;促进新能源发电的消纳&#xff0c;储能将成为至关重要的一环&#xff0c;是分布式光伏、风电等新能源消…

LeetCode 40.组合总和 II

组合总和 II 给定一个候选人编号的集合 candidates 和一个目标数 target &#xff0c;找出 candidates 中所有可以使数字和为 target 的组合。 candidates 中的每个数字在每个组合中只能使用 一次 。 注意&#xff1a;解集不能包含重复的组合。 方法一、回溯 由于题目要求解集…

第十九周周报

文章目录 摘要文献阅读DeepHuman: 3D Human Reconstruction from a Single Image(ICCV 2019)贡献摘要网络结构总结 PIFu: Pixel-Aligned Implicit Function for High-Resolution Clothed Human Digitization贡献摘要网络结构总结 Animated 3D human avatars from a single imag…

多项式乘法逆(p4238 NTT)

题目路径&#xff1a; https://www.luogu.com.cn/problem/P4238 思路&#xff1a; 代码&#xff1a; #define _CRT_SECURE_NO_WARNINGS #include<iostream> #include<string> #include<cstring> #include<cmath> #include<ctime> #include&l…

有什么办法可以让模糊的老照片变清晰?这几个方法收藏好!

照片盒子里的老照片&#xff0c;宛如一扇陈旧的时光之门&#xff0c;等着我们去开启。那些尘封的记忆&#xff0c;似乎已经被时间遗忘&#xff0c;但当我们轻轻拂去尘埃&#xff0c;那些熟悉的画面便再次浮现在眼前。然而&#xff0c;岁月无情&#xff0c;这些宝贵的瞬间在时间…