虚拟列表的实现原理

1 篇文章 0 订阅
1 篇文章 0 订阅

这是我在面试题中遇到的一个问题,就是如何优化前端性能,其中虚拟列表也是优化前端性能的一种方法。

原理:

 当页面加载的数据很多时,会让浏览器的性能降低,此时我们可以按需加载,只加载我们可以看到的区域,而虚拟列表就是这个功能。

代码:

<!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>Document</title>
  </head>

  <body>
    <div id="list-container">
      <div id="list-wrapper">
        <div id="list-viewport">
          <!-- 可视区域内的列表项会动态渲染,其余项则不会渲染 -->
          <ul>
            <li>1</li>
            <li>2</li>
            <li>3</li>
            <li>4</li>
            <li>5</li>
            <li>6</li>
            <li>7</li>
            <li>8</li>
            <li>9</li>
            <li>0</li>
            <li>9</li>
            <li>7</li>
            <li>6</li>
            <li>4</li>
            <li>2</li>
            <li>2</li>
            <li>5</li>
            <li>7</li>
            <li>5</li>
            <li>3</li>
            <li>2</li>
            <li>34</li>
            <li>23</li>
            <li>23</li>
            <li>1</li>
            <li>6</li>
            <li>1</li>
            <li>8</li>
            <li>1</li>
            <li>8</li>
          </ul>
        </div>
      </div>
    </div>
  </body>
  <script>
    const listContainer = document.getElementById("list-container");
    const listViewport = document.getElementById("list-viewport");

    // 计算每个列表项的高度,例如每个项目高度为 50px。
    const ITEM_HEIGHT = 50;

    // 计算列表项总数,例如有 1000 个列表项。
    const ITEM_COUNT = 1000;

    // 计算可视区域内最多可容纳几个列表项。
    const VISIBLE_ITEM_COUNT = Math.ceil(
      listContainer.clientHeight / ITEM_HEIGHT
    );

    // 监听滚动事件,计算需要展示的列表项和其位置。
    listContainer.addEventListener("scroll", () => {
      const scrollTop = listContainer.scrollTop;
      const startIndex = Math.floor(scrollTop / ITEM_HEIGHT);
      const endIndex = Math.min(startIndex + VISIBLE_ITEM_COUNT, ITEM_COUNT);

      // 动态渲染可视区域内的列表项。
      let itemsHtml = "";
      for (let i = startIndex; i < endIndex; i++) {
        itemsHtml += `<div class="list-item" style="top:${
          i * ITEM_HEIGHT
        }px;">${i}</div>`;
      }
      listViewport.innerHTML = itemsHtml;
    });
  </script>
</html>
<style>
  #list-container {
    overflow-y: auto; /* 设置容器为滚动条自动出现 */
    height: 300px; /* 设置容器高度 */
  }

  #list-viewport {
    position: relative; /* 设置列表视口为相对定位 */
  }

  .list-item {
    position: absolute; /* 设置列表项为绝对定位,便于后面计算位置 */
  }
</style>

总结出的步骤就是

1、设置每个item项的高度 、最多有几个item ,利用listContainer.clientHeight可视区域高度/item的高度,从而求出可视区域有几个item

2、添加监听事件scroll,通过鼠标滚动的高度求出可视区域第一个item的索引(startIndex),再根据可视区域可展示的总数(VISIBLE_ITEM_COUNT)计算出可视区域最后一个item的索引

3、最后渲染到list-viewport里面

有什么不对的地方请多指指点点喔~~

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Anersen

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值