一次渲染十万条数据:前端技术优化(上)

今天看了一篇文章,写的是一次性渲染十万条数据的方法,本文内容是对这篇文章的学习总结,以及知识点补充。

在现代Web应用中,前端经常需要处理大量的数据展示,例如用户评论、商品列表等。直接渲染大量数据会导致浏览器性能问题,如卡顿和延迟。本文将探讨几种优化策略,帮助开发者提高网页性能,优化用户体验。

方法一:通过document直接渲染十万条数据

示例代码

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>一次性渲染十万条数据</title>
</head>
<body>
  <ul id="app"></ul>
</body>
<script>
  const app = document.querySelector('#app')
  let now = Date.now()
  // 方法一:一次性渲染十万条数据
  for (let i = 0; i < 100000; i++) {
     
   const li = document.createElement('li')
   li.innerText = `我是第${
       i + 1}条数据`
   app.appendChild(li)
  }


  console.log('js运行耗时', Date.now() - now)

  setTimeout(() => {
     
    console.log('dom渲染耗时', Date.now() - now)
  })
  
</script>
</html>

结果

请添加图片描述

问题

当页面需要一次性渲染大量数据时,直接将所有数据渲染到DOM中会迅速消耗浏览器资源,造成性能瓶颈。这种方法虽然简单,但会导致浏览器响应缓慢,用户体验差。

补充知识1: JS事件循环之宏任务和微任务

在 JavaScript 中,事件循环是处理并发的机制,它允许执行非阻塞的操作。事件循环的核心概念包括宏任务(macro tasks)和微任务(micro tasks)。它们的执行顺序和机制十分重要,理解它们有助于更好地编写异步代码。

宏任务与微任务
  1. 宏任务 (Macro Task):

    • 宏任务是较大粒度的任务,它通常由以下几部分组成:
      • 整个脚本(执行的上下文)
      • setTimeout
      • setInterval
      • I/O 操作(如网络请求)
    • 宏任务的执行是按照创建顺序依次执行的。
  2. 微任务 (Micro Task):

    • 微任务是相对较小粒度的任务,通常用于处理短小的异步操作,主要由以下几部分组成:
      • Promise.then().catch()
      • MutationObserver
    • 微任务在当前宏任务执行完毕后立即执行,且在浏览器进行下一次重绘之前完成所有微任务。这意味着微任务的优先级高于宏任务。
执行顺序
  1. 首先,事件循环从宏任务队列中取出一个宏任务并执行。
  2. 执行完宏任务后,查看微任务队列,执行所有微任务,直到微任务队列为空。
  3. 一旦微任务队列为空,浏览器会进行渲染(重绘),然后再从宏任务队列中取出下一个宏任务。
  4. 重复这个过程,直到所有任务都完成。
示例

下面是一个简单的示例,帮助理解宏任务和微任务的执行顺序:

console.log('Start');

setTimeout(() => {
   
  console.log('Timeout 1');
}, 0);
### 微信小程序地图组件分批加载 Markers 的实现方法 在微信小程序的地图组件中,当需要展示大量标记点(markers)时,一次性加载过多的 markers 可能会影响性能和用户体验。为了优化这一情况,可以通过分批次加载的方式逐步呈现这些标记点。 #### 方法一:基于滚动事件触发加载更多数据 通过监听用户的滑动行为来动态增加新的 marker 数据集。具体做法是在页面初始化时只加载部分 markers,并设置一个标志位用于记录当前已加载的数据量。每当用户接近地图边界或特定区域时,则自动请求下一批次的数据并更新至地图上[^1]。 ```javascript Page({ data: { markers: [], // 存储所有的marker信息 loadedCount: 0, // 已经加载了多少个marker totalMarkers: [] // 所有要显示的marker列表 }, onLoad() { const initialLoadSize = 5; // 每次加载的数量 this.setData({ markers: this.data.totalMarkers.slice(0, initialLoadSize), loadedCount: initialLoadSize }); wx.createMapContext('myMap').onRegionChange((res) => { if (res.type === 'end') { // 当停止移动后判断是否需要加载新数据 let newLoadedCount = Math.min(this.data.loadedCount + initialLoadSize, this.data.totalMarkers.length); if(newLoadedCount !== this.data.loadedCount){ this.setData({ markers: [...this.data.markers,...this.data.totalMarkers.slice(this.data.loadedCount,newLoadedCount)], loadedCount:newLoadedCount }) } } }); } }) ``` #### 方法二:利用时间间隔定时刷新 另一种策略是每隔一段时间就向服务器查询一次最新的位置信息并将它们作为新增加的 markers 添加到现有集合当中去。这种方式适用于实时性较高的应用场景,比如跟踪车辆行驶轨迹等场景下的 Marker 更新需求。 ```javascript setInterval(() => { // 假设每次获取最多20最新数据 fetchLatestPositions().then(positions => { const currentMarkers = this.data.markers; positions.forEach(pos => { if (!currentMarkers.find(marker => marker.id === pos.id)) { currentMarkers.push({ id: pos.id, latitude: pos.latitude, longitude: pos.longitude, iconPath: '/images/marker.png' }); } }); this.setData({ markers: currentMarkers }); }).catch(err => console.error('Failed to load latest positions:', err)); }, 60 * 1000); // 每分钟执行一次 ``` 这两种方式都可以有效地减少初次渲染的压力以及提高交互过程中的流畅度。开发者可以根据实际业务逻辑选择合适的方法来进行实现。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值