【VUE】关于长列表优化2022

设置box 显示区域 达到区域内滚动 并监听滚动事件

代码如下:

<template>
    <div class="box" ref="box" @scroll="handleScroll">
        <ul class="list" ref="list" :style="{ transform: getTransform }">
            <li class="item" v-for="(item, index) in visibaleData" :key="index">{{item}}{{index}}</li>
            <div v-if="loadShow">加载中....</div>
        </ul>
    </div>
</template>
<style lang="scss" scoped>
.box {
  width: 600px;
  height: 60vh;
  background: #fff;
  position: relative;
  overflow-y: scroll;
  color: #4196FF;
  .list {
    width: 100%;
    .item {
      width: 100%;
      height: 60px;
      border: 1px solid #000;
      box-sizing: border-box;
    }
  }
}
::-webkit-scrollbar{
  display: none;
}
</style>

数据处理逻辑及初始化

获取真实数据 (list

设置每一个列的高度值(itemHeight

获取显示区域高度 (offsetHeight

计算显示区域的数量 (visibaleCount

记录可视区域的第一(startIndex)和最后一个元素(endIndex

根据startIndexendIndex的值 计算可视区域起始到结束的数据赋值 (visibaleData

监听滚动事件 

利用 $refs 获取滚动距离(scroll  = this.$refs.box.scrollTop

计算滚动了多少个列(Math.floor(scroll / itemHeight))并修改startIndex的位置

startIndex值修改 即重新计算 endIndex 的值 = startIndex + visibaleCount

并手动设置滚动距离 getTransform

利用 endIndex 比对 list.length 进行数据加载  利用loadShow 实现节流if (this.endIndex > this.list.length)

最后重新计算可视区域渲染的数据 updateVisibleData()

备注:可视区高度可动态获取不固定 但是itemHeight每个列的高度得固定  这是弊端 有更好方法的请多多指点 

代码如下:

<script>
export default {
  data() {
    return {
      // offsetHeight: 600, //初始化可视区域高度
      itemHeight: 60, //每个列的高度
      visibaleCount: 0, //可视区域的渲染的个数
      // allHeight: 0, //总数据的高度
      visibaleData: [], //可视区域渲染的数据集合
      list: [], //总数据
      startIndex: 0, //可视区域的第一个元素
      endIndex: 0, //可视区域的最后一个元素
      bufferSize: 6, // 首次缓冲值
      getTransform: 0, //滚动距离
      loadShow: false, // 阻止多次触发
    };
  },
  mounted() {
    // 初始化数据
    for (let i = 0; i < 10; i++) {
      this.list.push("item");
    }
    this.init(true)
  },
  
  methods: {
    // 初始化数据
    init(first) {
      if (first) {
        // 动态获取显示区域的高度
        // this.offsetHeight = this.$refs.box.offsetHeight
        // 计算显示区域可以渲染的数量
        this.visibaleCount =
          Math.floor(this.$refs.box.offsetHeight / this.itemHeight) + this.bufferSize;
        // 可视区域的最后一个元素
        this.endIndex = this.startIndex + this.visibaleCount;
      }
      // 计算全部数据的高度
      // this.allHeight = this.list.length * this.itemHeight;
      this.updateVisibleData();
    },
    //可视区域渲染的数据
    updateVisibleData() {
      //  如果不显示.load 可this.endIndex+1 增加一个列的缓冲区域
      this.visibaleData = this.list.slice(this.startIndex, this.endIndex);
    },
    // 滚动触发
    handleScroll(e) {
      if(this.loadShow) return
      let scroll = this.$refs.box.scrollTop;
      this.startIndex = Math.floor(scroll / this.itemHeight);
      // 可视区域的最后一个元素
      this.endIndex = this.startIndex + this.visibaleCount;
      //让滚动距离为itemHeight整数倍,
      this.getTransform = `translate3d(0,${scroll -
        (scroll % this.itemHeight)}px,0)`;
        console.log(scroll -
        (scroll % this.itemHeight))
      if (this.endIndex > this.list.length) {
        this.loadShow = true
        // 仿制数据加载
        setTimeout(() => {
          for (let i = 0; i < 10; i++) {
            this.list.push("item");
          }
          this.loadShow = false
  
        }, 1000)
        return
      }
      this.updateVisibleData();
    }
  }
};
</script>

完整demohttps://download.csdn.net/download/weixin_39007040/85028960

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值