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

news/2024/6/1 21:56:31 标签: react.js, LazyBuilder, 前端

前言:

        在一个表格中,需要展示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.niftyadmin.cn/n/5351835.html

相关文章

网工每日一练(1月29日)

试题1 CPU:执行算术运算或者逻辑运算时&#xff0c;常将源操作数和结果暂存在&#xff08;B&#xff09;中。A.程序计数器 (PC)B.累加器 (AC)C.指令寄存器 (IR)D.地址寄存器 (AR) 加寄存器ac通常简称为累加器&#xff0c;其功能是:当运算器的算术逻辑单元alu执行算术或逻辑运…

JavaEE-自定义SSM-环境搭建-测试程序

1. 环境搭建 1.1 结构说明 1.2 创建父项目 项目名&#xff1a;myssm-parent-quan12 1.3 创建核心项目 项目名&#xff1a;myssm-core-quan12 配置pom文件&#xff08;4个坐标&#xff09; <dependencies><!-- 内置tomcat --><dependency><groupId>…

php小数四舍五入、向上取整、向下取整

简单示例 1、round 对浮点数进行四舍五入 $result round(3.456, 2); var_dump($result);// 输出结果为&#xff1a;double(3.46)$result round(3.451, 2); var_dump($result);// 输出结果为&#xff1a;double(3.45) 2、ceil 进一取整:向上取整返回下一个最高的整数 $r…

【leetcode刷刷】669. 修剪二叉搜索树 、108.将有序数组转换为二叉搜索树 、538.把二叉搜索树转换为累加树

669. 修剪二叉搜索树 一些递归&#xff0c;有点点绕&#xff0c;但画了一下示意图就差不多能理清 class Solution:def trimBST(self, root: Optional[TreeNode], low: int, high: int) -> Optional[TreeNode]:# 修剪树——保留原来的父代子代关系# 遇到的第一个小于low的节…

K8s 安装部署-Master和Minion(Node)

K8s 安装部署-Master和Minion(Node) 操作系统版本&#xff1a;CentOS 7.4 Master &#xff1a;172.20.26.167 Minion-1&#xff1a;172.20.26.198 Minion-2&#xff1a;172.20.26.210&#xff08;后增加节点&#xff09; ETCD&#xff1a;172.20.27.218 先安装部署ETCD y…

南京观海微电子---如何减少时序报告中的逻辑延迟

1. 引言 在FPGA逻辑电路设计中&#xff0c;FPGA设计能达到的最高性能往往由以下因素决定&#xff1a; ▪ 工作时钟偏移和时钟不确定性&#xff1b; ▪ 逻辑延迟&#xff1a;在一个时钟周期内信号经过的逻辑量&#xff1b; ▪ 网络或路径延迟&#xff1a;Vivado布局布线后引…

C++20 高级编程

文章目录 前言前奏lambda浅谈std::ref的实现浅谈is_same浅谈std::function的实现std::visit 与 std::variant 与运行时多态SFINAE类型内省标签分发 (tag dispatching)软件设计六大原则 SOLID To be continue.... 前言 C20 是C在C11 之后最大的一次语言变革, 其中引入了大量具有…

【架构】Docker实现集群主从缩容【案例4/4】

实现集群主从缩容【4/4】 接上一节&#xff0c;在当前机器为4主4从的架构上&#xff0c;减缩容量为3主3从架构。即实现删除6387和6388. 示意图如下&#xff1a; 第一步&#xff1a;查看集群情况&#xff08;第一次&#xff09; redis-cli --cluster check 127.0.0.1:6387roo…