vue长列表思路及代码实现

29 阅读1分钟

virtalList.vue 虚拟滚动组件简单实现

实现思路
  1. 能滚动的盒子 container
  2. scroll-bar 滚动条,滚动条的高度 barHeight = this.size(每条数据的高度) * this.visibleData.length(总数据条数) + 'px'
  3. scroll-list容器,真实显示的列表容器。listTop 记录列表占据滚动条的高度,确保scroll-list一直在可视范围内。
  4. visibleData 总的数据 size 每条数据的高度 listTop 记录列表占据滚动条的高度 showNumber 每页展示的条数 start 数据截取的开始位置 end = start + showNumber 数据截取的结束位置
  5. handlScroll方法 滚动的时候记录滚动高度 const scrollTop = this.$refs.container.scrollTop; 动态计算start = Math.floor(scrollTop / size),向下取整。end = start + showNumber,动态截取可显示的数据条数 showData = this.visibleData.slice(this.start, this.end)
<template>
  <!-- 能滚动的盒子 -->
  <div class="container" ref="container" @scroll="handlScroll">
    <!-- 滚动条 -->
    <div class="scroll-bar" :style="{ height: barHeight }" ref="scrollbar"></div>
    <!-- 列表位置 -->
    <div class="scroll-list" :style="{top: listTop}">
      <div v-for="item in showData" :style="{ height: size + 'px' }" ref="items" :key="item.id">
        <!-- 通过插槽传出去 -->
        <slot :item="item"></slot>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  props: {
    visibleData: {
      type: Array,
      default: () => {}
    },
    // 每条数据的高度
    size: {
      type: Number,
      default: 0
    },
    // 每次渲染几个dom节点
    showNumber: {
      type: Number,
      default: 0
    }
  },
  data() {
    return {
      start: 0,
      end: this.showNumber,
    }
  },
  computed: {
    // 每次渲染的数据
    showData() {
      // start end 截取数据
      return this.visibleData.slice(this.start, this.end)
    },

    // 滚动条的高度
    barHeight() {
      return this.visibleData.length * this.size + 'px'
    },

    // 列表滑动的高度
    listTop() {
      return this.start * this.size + 'px'
    },
  },
  methods: {
    handlScroll() {
      
      const scrollTop = this.$refs.container.scrollTop;
      // 滑动高度除以每个节点的高度等于start的值
      this.start = Math.floor(scrollTop / this.size);
      // start的值加上每页渲染的数据 就是end的值
      this.end= this.start + this.showNumber;
    },
  }
}
</script>

<style>
.container {
  overflow-y: scroll;
  position: relative;
  background: #eee;
  width: 100%;
  height: 100vh;
}
.scroll-list {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
}
</style>

使用virtalList组件

import virtalList from './virtalList.vue'
<virtalList :size="40" :showNumber="30" :visibleData="visibleData">
  <template #default="{ item }">
    <div>{{ item.content }}</div>
  </template>
</virtalList>
// visibleData(很多条数据)