虚拟列表:性能优化

虚拟列表是一种有效的前端性能优化策略,通过只渲染可视区域及相邻元素,减少大量DOM操作,提高滚动流畅性。本文将探讨如何利用HTML和JavaScript实现虚拟列表。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

虚拟列表用于前端列表性能优化,通过对数据的截取和展示区域的定位,达到只渲染展示区域+1数量的列表项,以下为代码

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>virtual-list</title>
  <style>
    .context {
      position: relative;
      width: 500px;
      max-height: 600px;
      background-color: #cccccc;
      overflow: auto;
    }

    .virtual-context {
      position: absolute;
      left: 0;
      right: 0;
      z-index: -1;
    }

    .real-context {
      position: absolute;
      left: 0;
      right: 0;
      transform: translate3d(0);
    }

    .real-item {
      width: 100%;
      height: 150px;
      background-color: #f2f2f2;
      text-align: center;
      line-height: 150px;
    }
  </style>
</head>

<body>
  <div id="context" class="context">
    <!-- 用于撑开context -->
    <div id="virtualContext" class="virtual-context"></div>
    <!-- 用于渲染列表项 -->
    <div id="realContext" class="real-context">
    </div>
  </div>

  <script>
    const data = [
      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12
    ]
    const context = document.getElementById('context')
    const virtualContext = document.getElementById('virtualContext')
    const realContext = document.getElementById('realContext')
    // 列表每项高度
    const itemHeight = 150
    // 列表父容器的最大高度
    const maxHeight = 600
    // 列表最多展示数量
    const itemNum = Math.ceil(maxHeight/itemHeight) + 1
    // 根据数据量设置列表父容器高度
    context.style.height = data.length * itemHeight >= maxHeight ? maxHeight + 'px' : data.length * itemHeight + 'px'
    // 根据数据量设置父容器的滚动高度,控制是否展示滚动条
    virtualContext.style.height = data.length * itemHeight + 'px'
    // 数据截取起始
    let start = 0;
    // 数据截取终点
    let end = data.length > (start + itemNum) ? (start + itemNum) : data.length
    // 渲染列表项
    const renderList = () => {
      let str = ''
      for (let i = start; i < end; i++) {
        str += `<div class="real-item">${data[i]}</div>`
      }
      realContext.innerHTML = str
    }
    renderList()
    context.onscroll = (e) => {
      const scrollTop = e.target.scrollTop
      const scrollHeight = e.target.scrollHeight
      const clientHeight = e.target.clientHeight
      // 如果滚动条触底则不继续执行
      if (scrollHeight - scrollTop !== clientHeight) {
        // 根据滚动距离和列表项高度,获取新起点
        const newStart = Math.floor(scrollTop / itemHeight)
        // 优化:如果起点不变,不执行渲染
        if (newStart !== start) {
          start = newStart
          end = data.length > (start + itemNum) ? (start + itemNum) : data.length
          // 重点:设置列表距离顶部高度
          const offsetTop = scrollTop - (scrollTop % itemHeight)
          realContext.style.transform = `translate3d(0, ${offsetTop}px, 0)`
          renderList()
        }
      }
    }
  </script>
</body>

</html>

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值