虚拟列表

98 阅读1分钟
/**
 * 1: virtualizationList 虚拟列表数据
 * 2: parenBox 父盒子的高度
 * 3: listBox 存放子元素的且可滚动的盒子
 * 4: itemHeight 子元素的高度
 * 5: itemNumber 显示多少个
 */
 
class virtualizationList {
  constructor(
    virtualizationList,
    parenBox,
    listBox,
    itemNumber = 5,
    itemHeight = 200
  ) {
    this.virtualizationList = virtualizationList;
    this.parenBox = document.querySelector(parenBox);
    this.listBox = document.querySelector(listBox);
    this.itemHeight = itemHeight;
    this.itemNumber = itemNumber; // 记录默认显示的子元素个数
    this.scrollIndex = 0; // 记录滚起来几个item
    this.visualList = []; // 可视区显示数据
  }

  // 初始化  
  init() {
    let self = this;
    this.visualList = this.virtualizationList.slice(0, this.itemNumber); // 默认显示个数
    this.setDom()// 初始化第一波
    this.listBox.addEventListener("scroll", function () {
      // 在滚动时执行的操作
      let scrollIndex = Math.ceil(self.listBox.scrollTop / self.itemHeight); // 监测滚动了几个元素上去
      if(scrollIndex <= self.scrollIndex ) return // 必须是向下滚动才需要加载dom,否则就是已经加载过的dom了
      self.scrollIndex = scrollIndex;
      let item = self.virtualizationList[self.visualList.length]
      item && self.visualList.push(item) // 解决添加完成后还在继续添加undefind
      self.setDom()
    });
  }
  setDom(){
    this.visualList.forEach(item => {
      if(item.flag) return; // 子元素已经被添加过了
      var newDiv = document.createElement("div");
      newDiv.textContent = item.i;
      newDiv.style.height = this.itemHeight+'px'
      newDiv.style.borderBottom = '1px solid #000';
      this.listBox.appendChild(newDiv);
      item.flag = true;
    })
  }
}
// 1: 使用实例
// 模拟大量数据
let arr = [];
for (let i = 0; i < 100; i++) {
  arr.push({i,});
}

const V = new virtualizationList(
  arr,
  ".virtualization_parent",
  ".virtualization_list"
);
V.init();