大量数据的优化之虚拟滚动和web workers

本文介绍了如何通过虚拟滚动技术、利用WebWorkers异步处理大量数据以及实施分页加载、懒加载和列懒加载策略,有效减少DOM元素,提升网页的渲染速度和响应能力。
摘要由CSDN通过智能技术生成

1.虚拟滚动:

只渲染可见区域,而不是把所有数据全部渲染出来。这样极大的减少了dom元素数量,加速了渲染速度。

通过设置内容容器的高度来容纳所有数据,然后定义一个函数根据滚动的位置计算出可见区域的数据范围,再使用渲染函数传入可见数据的范围进行只渲染可见区域的数据。

(1)设置每条数据的高度和容纳所有数据的高度

(2)主要是使用scrollTop找出卷去的高度,clientHeight找出数据可见区域的高度。

(3)第一个数据index:scrollTop/itemHeight 然后使用Math.floor进行向下取整。

(4)最后一个index: scrollTop+clientHeight/itemHeight  然后用Math.ceil向上取整

(5)然后放入渲染函数中for循环用document.createElement('div');一个个创建div。

(6)最后,添加一个事件监听器container.addEventListener('scroll', renderVisibleItems);

(7)在这个修改后的代码中, 函数模拟了一个数据源,根据索引返回对应的数据。在渲染 函数中,每次创建div 元素时调用 getData函数来填充相应的数据,从而实现了根据可见区域动态渲染数据的效果。

1.虚拟滚动:只渲染可见区域的数据行,而不是将所有数据都一次性渲染出来。这样可以极大地减少DOM元素的数量,提升页面的加载速度和渲染性能。

(1).我们通过设置内容容器的高度来容纳所有数据,然后根据滚动的位置计算出可见区域的数据范围,仅渲染可见区域的数据。

(2).使用组件库:react-virtualized:它提供了一系列用于虚拟滚动的组件,包括列表、表格等。它支持动态高度和宽度,可以适应各种复杂的布局。

react-window:提供了一系列高性能的虚拟滚动组件,如列表、网格、表格等。react-window更轻量、更易于集成和定制。

<body>
  <div id="container">
    <div id="content"></div>
  </div>
  <script>
    const container = document.getElementById('container');
    const content = document.getElementById('content');
    const itemHeight = 50;
    const totalItems = 1000; // 假设有1000条数据

    // 设置内容容器的高度,使其足够容纳所有数据
    content.style.height = `${itemHeight * totalItems}px`;

    // 模拟数据源
    function getData(index) {
      return `Item ${index + 1}`;
    }

    // 计算可见区域内的数据范围
    function calculateVisibleItems() {
      const scrollTop = container.scrollTop;
      const startIndex = Math.floor(scrollTop / itemHeight);
      const endIndex = Math.min(
        totalItems - 1,
        Math.ceil((scrollTop + container.clientHeight) / itemHeight)
      );
      return { startIndex, endIndex };
    }

    // 渲染可见区域的数据
    function renderVisibleItems() {
      const { startIndex, endIndex } = calculateVisibleItems();
      // 清空内容容器
      content.innerHTML = '';
      // 仅渲染可见区域的数据,根据可见区域内的数据范围,动态地创建相应数量的元素并填充数据
      for (let i = startIndex; i <= endIndex; i++) {
        const item = document.createElement('div');
        item.className = 'item';
        item.textContent = getData(i); // 填充对应的数据
        content.appendChild(item);
      }
    }

    // 初始化渲染
    renderVisibleItems();

    // 监听滚动事件,实时更新可见区域的数据
    container.addEventListener('scroll', renderVisibleItems);
  </script>
</body>

2.使用Web Workers:

我们创建了一个包含 1000 行、每行 10 列的虚拟表格数据,并将其发送给 Web Worker 进行处理。Web Worker 将会将每个单元格内容转换为大写字母,并将处理后的数据发送回主线程。

通过这种方式,可以在不阻塞主线程的情况下处理大量数据,从而提高页面的性能和响应速度。

workers:
// 在 Web Worker 中处理数据
self.addEventListener('message', function(e) {
    // 接收主线程发送的数据
    var data = e.data;
    // 在这里进行数据处理或计算操作
    var result = processData(data);
    // 将处理结果发送回主线程
    self.postMessage(result);
});
​
function processData(data) {
    // 在这里进行数据处理或计算操作
    // 这只是一个示例,实际操作根据具体需求编写
    return data.map(row => row.map(cell => cell.toUpperCase()));
}
main.js:
// 创建 Web Worker 实例
const worker = new Worker('worker.js');
​
// 模拟大量数据
const data = [];
for (let i = 0; i < 1000; i++) {
    const row = [];
    for (let j = 0; j < 10; j++) {
        row.push(`Row ${i + 1}, Cell ${j + 1}`);
    }
    data.push(row);
}
​
// 向 Web Worker 发送数据
worker.postMessage(data);
​
// 接收 Web Worker 处理后的结果
worker.addEventListener('message', function(e) {
    const result = e.data;
    console.log('处理后的数据:', result);
});
​

其他方法:

3.分页加载:

将数据分页加载,每次只加载当前页的数据,而不是一次性加载所有数据。这样可以减少一次性加载大量数据所带来的性能问题,提升页面的响应速度。

4.懒加载:

只在用户需要时加载数据,而不是提前加载所有数据。例如,当用户滚动到表格底部时,再动态加载下一页的数据。

5.列的懒加载:

只渲染当前可见区域的列,而不是一次性渲染所有列。当用户水平滚动表格时,动态加载新的列数据。

6.数据缓存:

将经常使用的数据缓存到内存或者LocalStorage中,减少重复请求数据的次数。

  • 5
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
使用Web Worker来计算大量数据贴地的过程可以分为以下几步: 1. 在主线程中创建一个Web Worker对象,指定要执行的计算任务的代码文件路径。 ```javascript const worker = new Worker('worker.js'); ``` 2. 在Worker代码文件中,使用postMessage()方法将计算任务分发到Worker线程中执行。 ```javascript // worker.js self.addEventListener('message', (e) => { const data = e.data; // 执行计算任务 const result = calculate(data); // 将计算结果发送回主线程 self.postMessage(result); }); ``` 3. 在主线程中监听Worker线程的message事件,获取计算结果。 ```javascript worker.addEventListener('message', (e) => { const result = e.data; // 处理计算结果 }); ``` 4. 将需要计算的大量数据分割成小块,逐个发送给Worker线程进行计算,并在计算完成后合并结果。 ```javascript const chunkSize = 1000; // 每次处理的数据块大小 const totalChunks = Math.ceil(data.length / chunkSize); // 数据块数量 let completedChunks = 0; // 已完成的数据块数量 let results = []; // 存储计算结果 for (let i = 0; i < totalChunks; i++) { const start = i * chunkSize; const end = Math.min(start + chunkSize, data.length); const chunk = data.slice(start, end); // 发送数据块到Worker线程 worker.postMessage(chunk); // 监听计算结果 worker.addEventListener('message', (e) => { const result = e.data; results.push(result); completedChunks++; if (completedChunks === totalChunks) { // 所有数据块都已计算完成,处理最终结果 const finalResult = mergeResults(results); // TODO: 处理最终结果 } }); } ``` 5. 在Worker线程中,使用Cesium的SampledProperty对象对贴地数据进行插值计算,并将计算结果返回给主线程。 ```javascript // worker.js import { SampledProperty } from 'cesium'; function calculate(data) { const property = new SampledProperty(Number); // 创建一个SampledProperty对象 // 向SampledProperty对象添加样本点,x轴为时间,y轴为高度 for (let i = 0; i < data.length; i++) { const time = data[i].time; const height = data[i].height; property.addSample(time, height); } // 对SampledProperty对象进行插值计算,获取贴地高度值 const result = []; for (let i = 0; i < data.length; i++) { const time = data[i].time; const position = data[i].position; const height = property.getValue(time); result.push({ position, height }); } return result; } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值