虚拟化长列表

在高度固定且可滚动的容器内渲染有限数量的节点。

  • height:500px;overflow:auto的容器内,假如每行节点height:50px,那么10行这样的节点便可填满容器。
  • 每行节点height:50px,假如有1000行这样的节点,那么,全部节点的高度和便是50*1000=50000px,这足以撑开容器得到滚动条。
  • 监听容器的scroll事件,可获取滚动的垂直距离srollTop,从而计算出此时应该渲染第几行节点。
  • 如果滚动过快,可能会出现闪烁,可预先渲染几行,比如,10行50px的节点可填满高500px的固定容器,那么一开始就渲染12行15行
  • 为避免快速滚动导致的频繁渲染,可通过节流来控制渲染速率。
<body>
<div class="container">
  <ul class="content"></ul>
</div>
</body>
  .container{
    width: 500px;
    height: 500px;
    border: 2px solid lightskyblue;
    overflow:auto;
  }
  .content{
    list-style: none;
    padding:0;
    margin:0;
    font-weight: bold;
    box-sizing:border-box;
  }
  li{
    height:50px;
    line-height: 50px;

  }
  li:nth-child(even){
    background-color:lightgoldenrodyellow
  }
  li:nth-child(odd){
    background-color: lightcyan;
  }
  const LEN = 1000;
  const HEIGHT = 50;
  const TOTAL_HTIGHT = LEN*HEIGHT;

  var content = document.querySelector(".content");
  content.style.height = TOTAL_HTIGHT + "px";

  var startIndex = 0;
  var endIndex = 15;
  var list = initList();
  var visibleList = list.slice(startIndex,endIndex);
  content.innerHTML = visibleList.join(" ");

  var container = document.querySelector(".container");
  // container.addEventListener("scroll",loadVisibleList);
  container.addEventListener("scroll", throttle(loadVisibleList));
    // container.addEventListener("scroll",throttle_raf(loadVisibleList));


  
  function initList(){
    const list = [];
    for(var i=0;i<LEN;i++){
      var liElm = `<li>${i+1}</li>`;
      list.push(liElm);
    }
    return list;
  }

  function loadVisibleList(){
    var scrollTop = container.scrollTop;
    content.innerHTML = "";
    startIndex = Math.floor(scrollTop/HEIGHT);
    content.style.paddingTop = startIndex * HEIGHT+"px";
    endIndex = startIndex+15;
    visibleList = list.slice(startIndex,endIndex).join(" ");
    content.innerHTML = visibleList;
    console.log("scroll");
  }

  // function throttle_raf(fn,context){
  //   var args = Array.prototype.slice.call(arguments,2);
  //   var requestId = null;
  //   return function(){
  //     if(requestId!==null) return;
  //     var finalArgs = args.concat(Array.prototype.slice.call(arguments));
  //     requestId = requestAnimationFrame(() => {
  //       fn.apply(context,finalArgs);
  //       requestId = null;
  //     });
  //   }
  // }

  function throttle(fn,context,delay=100){
    var args = Array.prototype.slice.call(arguments,3);
    var timer = null;
    return function(){
      if(timer!=null) return;
      var finalArgs = args.concat(Array.prototype.slice.call(arguments));
      timer = setTimeout(() => {
        fn.apply(context,finalArgs);
        timer = null;
      },delay);
    }
  }

在这里插入图片描述

参考文章
虚拟化长列表
长列表性能优化

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值