React渲染超大的字符串

import React, { useState, useEffect, useRef } from 'react';

const BigTextViewer = ({ text, chunkSize = 10000 }) => {
  const [visibleChunks, setVisibleChunks] = useState([]);
  const [currentIndex, setCurrentIndex] = useState(0);
  const containerRef = useRef(null);

  useEffect(() => {
    if (currentIndex * chunkSize >= text.length) return;

    const renderNextChunk = () => {
      const start = currentIndex * chunkSize;
      const end = Math.min(start + chunkSize, text.length);
      const chunk = text.substring(start, end);

      setVisibleChunks((prev) => [...prev, chunk]);
      setCurrentIndex((prev) => prev + 1);
    };

    // 使用requestAnimationFrame进行分批渲染
    if (currentIndex < 100) {
      // 初始快速渲染
      requestAnimationFrame(renderNextChunk);
    } else {
      // 后续慢速渲染,避免阻塞
      setTimeout(renderNextChunk, 0);
    }
  }, [currentIndex, text, chunkSize]);

  return (
    <div ref={containerRef} className="min-h-full whitespace-pre-wrap p-4 border rounded">
      {visibleChunks.map((chunk, index) => (
        <span key={index}>{chunk}</span>
      ))}
    </div>
  );
};

export default BigTextViewer;

在 React 里把一个超大的字符串分块渲染出来,避免一次性渲染导致浏览器卡顿

拆解一下逻辑 👇


📌 主要思路

  1. 分块切割字符串

    • chunkSize(默认 10000 个字符)把大文本切成一段一段。
    • 每次只渲染一段,而不是整个文本。
  2. 逐步渲染

    • requestAnimationFrame 在前 100 个分块时快速渲染(保证用户很快看到内容)。
    • 超过 100 块后,改用 setTimeout(异步队列)继续加载,避免主线程被长时间占用。
  3. 状态管理

    • visibleChunks 存储已经渲染的字符串块。
    • currentIndex 记录当前渲染到第几块。
  4. 渲染输出

    • 每个 chunk 作为一个 <span> 渲染,最终拼接成完整的大文本。
    • whitespace-pre-wrap 让空格和换行格式保持不变。

📌 执行过程

  • 初始 currentIndex = 0
  • useEffect 检查是否还有没渲染的块 → 切下一块 → 更新状态 → currentIndex + 1
  • 组件重新渲染 → useEffect 再次运行 → 继续下一块
  • 循环直到所有 chunk 渲染完。

📌 使用场景

  • 大日志文件预览
  • 代码文件(几十 MB)在线展示
  • 逐步加载长文本(小说、爬虫抓取的长文章)

📌 优点

✅ 不会卡死页面(因为分批渲染)。
✅ 用户能很快看到前面的内容,而不是等完整数据。
✅ 可调 chunkSize 控制性能 vs 流畅度。


📌 局限

⚠️ 所有渲染出来的内容还是会一直留在 DOM 里,超大文本(几百 MB)会造成 DOM 数量过多,拖慢滚动性能。
👉 如果是这种情况,就得结合 虚拟列表react-window / react-virtualized)来做。


React渲染 ECharts 图表,通常不会直接渲染 ECharts 的字符串表示形式,而是通过封装 ECharts 实例来实现图表的绘制。以下是一种常见的实现方式,结合 React 的生命周期机制(如 `useEffect` 或 `componentDidMount`)来初始化 ECharts 实例并绑定到 DOM 元素上 [^1]。 ### 使用 React + ECharts 渲染图表 #### 函数组件示例(使用 `useEffect`) ```jsx import React, { useRef, useEffect } from 'react'; import * as echarts from 'echarts'; function EChartsRadar({ option }) { const chartRef = useRef(null); const chartInstance = useRef(null); useEffect(() => { if (chartRef.current) { // 初始化 ECharts 实例 chartInstance.current = echarts.init(chartRef.current); // 设置图表配置项 chartInstance.current.setOption(option); } return () => { // 清理资源 if (chartInstance.current) { chartInstance.current.dispose(); } }; }, [option]); return <div ref={chartRef} style={{ width: '100%', height: '400px' }} />; } ``` 在上述代码中,`echarts.init` 方法将 DOM 元素作为容器初始化图表实例,并通过 `setOption` 方法设置图表配置对象 [^1]。 #### 类组件示例(使用 `componentDidMount`) ```jsx import React from 'react'; import * as echarts from 'echarts'; class EChartsLine extends React.Component { chart = null; componentDidMount() { const chartDom = document.getElementById('line-chart'); this.chart = echarts.init(chartDom); const option = { xAxis: { type: 'category', data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'] }, yAxis: {}, series: [{ data: [820, 932, 901, 934, 1290, 1330, 1320], type: 'line' }] }; this.chart.setOption(option); } componentWillUnmount() { if (this.chart) { this.chart.dispose(); } } render() { return <div id="line-chart" style={{ width: '100%', height: '400px' }} />; } } export default EChartsLine; ``` 该类组件在挂载后初始化 ECharts 实例,并在卸载时释放资源,避免内存泄漏 [^1]。 ### 图表配置项定义 ECharts 图表的外观和行为由 `option` 配置对象控制。该对象通常包括 `xAxis`、`yAxis`、`series`、`tooltip` 等字段。例如: ```javascript const option = { tooltip: { trigger: 'axis', formatter: (params) => { return `${params[0].name}<br/>` + params.map(p => `${p.marker} ${p.seriesName}: ${p.value}(${p.percent}%)`).join('<br/>'); } }, xAxis: { type: 'category', data: ['A', 'B', 'C', 'D'] }, yAxis: {}, series: [ { name: '销量', type: 'bar', data: [120, 200, 150, 80] }, { name: '产量', type: 'bar', data: [80, 150, 100, 200] } ] }; ``` 在 `formatter` 函数中,可以返回 HTML 字符串以实现更丰富的提示内容 [^4]。 ### 屏幕适配方案 在大屏项目中,推荐使用 `flexible + rem` 方案实现响应式布局。通过设置 `html` 元素的 `font-size`,结合 `postcss-pxtorem` 插件将 px 单位自动转换为 rem,从而实现不同分辨率下的适配 [^1]。 --- ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值