在React中实现分块导出大量数据表格并压缩成图片的解决方案

 更新时间:2024年12月19日 10:48:06   作者:snakeshe1010  
在现代Web开发中,处理和展示大量数据是一个常见的挑战,特别是在使用React框架时,我们经常需要将这些数据以表格的形式展示,并提供导出功能,本文将介绍如何在React中实现一个高效、分块导出大量数据表格,并将其压缩为图片的解决方案,需要的朋友可以参考下

需求分析

我们的目标是实现一个React组件,该组件能够:

  • 处理大量数据的表格展示。
  • 将表格数据分块导出为图片。
  • 压缩导出的图片以减少文件大小。

实现步骤

1. 获取表格数据

首先,我们需要一个函数来获取React表格组件的数据源:

const getTableData = (tableElement) => {
  const children = React.Children.only(tableElement.props.children);
  return children.props.dataSource || [];
}

2. 创建带数据的表格实例

接下来,我们需要一个函数来创建一个新的表格实例,并更新其数据源:

const createTableWithData = (element, data) => {
  const tableInstance = React.Children.only(element.props.children);
  return React.cloneElement(tableInstance.props.children, {
    ...tableInstance.props.children.props,
    dataSource: data
  });
}

3. 分块导出表格

为了处理大量数据,我们将数据分块,并为每个数据块创建一个表格实例,然后导出为图片:

const exportTableInChunks = async (element) => {
  const zip = new JSZip();
  const tableElement = element.querySelector('.ant-table-wrapper');
  const allData = getTableData(tableElement);
  const chunkSize = 200;
  const chunks = [];

  for (let i = 0; i < allData.length; i += chunkSize) {
    chunks.push(allData.slice(i, i + chunkSize));
  }

  const exportContainer = document.createElement('div');
  document.body.appendChild(exportContainer);
  const root = createRoot(exportContainer);

  try {
    const batchSize = 3;
    for (let i = 0; i < chunks.length; i += batchSize) {
      const currentBatch = chunks.slice(i, i + batchSize);
      await Promise.all(
        currentBatch.map(async (chunk, batchIndex) => {
          const newTable = createTableWithData(tableElement, chunk);
          root.render(
            <ConfigProvider theme={React.Children.only(children).props.children.props.theme}>
              {newTable}
            </ConfigProvider>
          );

          await new Promise((resolve) => setTimeout(resolve, 2000));

          const png = await exportElementAsPng(exportContainer, `${title}_part${i + batchIndex + 1}`);
          if (png) {
            zip.file(
              `${title}_part${i + batchIndex + 1}.png`,
              png.split('base64,')[1],
              { base64: true }
            );
          }
        })
      );
    }

    const content = await zip.generateAsync({ type: 'blob' });
    saveAs(content, `${title}.zip`);
  } finally {
    root.unmount();
    document.body.removeChild(exportContainer);
    resetExportState();
  }
}

4. 导出操作的触发

最后,我们需要一个函数来触发导出操作,并处理错误:

const handleExportContent = async (element) => {
  if (!element) {
    console.warn('Export element not found');
    return;
  }

  try {
    const tableData = getTableData(element);
    if (tableData.length > 200) {
      await exportTableInChunks(element);
    } else {
      const res = await exportElementAsPng(element, title, 'single');
      if (!res) {
        throw new Error('Failed to export image');
      }
    }
    resetExportState();
  } catch (error) {
    console.error('Export failed:', error);
    message.error('导出失败,请重试');
  }
}

5.补充导出图片的工具方法

  • 需要注意批量导出的需要转成base64然后压缩,单张的直接走单图片导出即可
import html2canvas from 'html2canvas'

export const exportElementAsPng = (
  element: HTMLElement,
  fileName: string = 'export',
  type?: string
) => {
  return new Promise((resolve, reject) => {
    // 添加最大尺寸限制
    const maxDimension = 16384 // 大多数浏览器的 Canvas 最大尺寸限制
    const elementRect = element.getBoundingClientRect()
    const scale = Math.min(
      2, // 原来的 2 倍缩放
      maxDimension / elementRect.width,
      maxDimension / elementRect.height
    )

    html2canvas(element, {
      backgroundColor: null,
      scale: scale,
      logging: false,
      useCORS: true, // 允许跨域图片
      allowTaint: true, // 允许跨域图片
      windowWidth: element.scrollWidth,
      windowHeight: element.scrollHeight
    })
      .then((canvas) => {
        // 创建下载链接
        if(type==='single'){
          const link = document.createElement('a')
          link.download = `${fileName}.png`
          link.href = canvas.toDataURL('image/png')
          link.click()
          resolve(true)
        }else{
          const base64String = canvas.toDataURL(type)
          resolve(base64String)
        }
      })
      .catch((error) => {
        reject(error)
      })
  })
}

结语

通过上述步骤,我们实现了一个能够处理React中大量数据表格的分块导出与图片压缩的功能。这种方法不仅提高了性能,还优化了用户体验,使得大量数据的导出变得更加高效和实用。

到此这篇关于在React中实现分块导出大量数据表格并压缩成图片的解决方案的文章就介绍到这了,更多相关React导出数据表格并压缩内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 详解React-Native解决键盘遮挡问题(Keyboard遮挡问题)

    详解React-Native解决键盘遮挡问题(Keyboard遮挡问题)

    本篇文章主要介绍了React-Native解决键盘遮挡问题(Keyboard遮挡问题),具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-07-07
  • 从零开始学习搭建React脚手架项目

    从零开始学习搭建React脚手架项目

    这篇文章主要介绍了从零开始学习搭建React脚手架项目,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-08-08
  • React Native react-navigation 导航使用详解

    React Native react-navigation 导航使用详解

    本篇文章主要介绍了React Native react-navigation 导航使用详解,详解的介绍了react-navigation导航的使用,具有一定的参考价值,有兴趣的可以了解一下
    2017-12-12
  • react-player实现视频播放与自定义进度条效果

    react-player实现视频播放与自定义进度条效果

    本篇文章通过完整的代码给大家介绍了react-player实现视频播放与自定义进度条效果,代码简单易懂,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧
    2022-01-01
  • React深入分析更新的创建源码

    React深入分析更新的创建源码

    React组件分为函数组件与class组件;函数组件是无状态组件,class称为类组件;函数组件只有props,没有自己的私有数据和生命周期函数;class组件有自己私有数据(this.state)和生命周期函数
    2023-01-01
  • npx create-react-app xxx创建项目报错的解决办法

    npx create-react-app xxx创建项目报错的解决办法

    这篇文章主要介绍了npx create-react-app xxx创建项目报错的解决办法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-02-02
  • react开发中如何使用require.ensure加载es6风格的组件

    react开发中如何使用require.ensure加载es6风格的组件

    本篇文章主要介绍了react开发中如何使用require.ensure加载es6风格的组件,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-05-05
  • 手把手带你用React撸一个日程组件

    手把手带你用React撸一个日程组件

    这篇文章主要给大家介绍了关于利用React撸一个日程组件的相关资料,包括日常组件的实现思路、使用的技术、以及遇到的技术难点,并给提供了详细的实例代码,需要的朋友可以参考下
    2021-07-07
  • React实现点击删除列表中对应项

    React实现点击删除列表中对应项

    本文主要介绍了React 点击删除列表中对应项的方法。具有一定的参考价值,下面跟着小编一起来看下吧
    2017-01-01
  • React中的跨组件通信的几种常见方法

    React中的跨组件通信的几种常见方法

    在React中,跨组件通信有几种常见的方式,每种方式适用于不同的场景,下面是几种常见的跨组件通信方法,感兴趣的朋友一起看看吧
    2025-04-04

最新评论