1. 程式人生 > 其它 >vue長列表渲染元件

vue長列表渲染元件

<template>
  <div>
    <!-- 能滾動的盒子 -->
    <div class="viewport" ref="viewport" @scroll="scrollListener" :style="`height:${boxH}px`">
      <!-- 滾動條 用於將父元素撐開,利用dom原生的滾動事件 -->
      <div class="scroll-bar" ref="scrollbar" :style="`height:${barH}px`"></div>
      <!-- 列表位置 -->
      <div
        class="scroll-list"
        :style="{ transform: `translate3d(0,${offset}px,0)`,top:`${offset_top}px` }"
        ref="list"
      >
        <div v-for="item in visibleData" :key="item._id" ref="a">
          <!-- 通過插槽傳出去 -->
          <slot :row="item"></slot>
        </div>
      </div>
    </div>
  </div>
</template>
<script>
export default {
  name: "biglist",
  props: {
    // 需要渲染的資料列表
    dataList: {
      type: Array,
      default: () => {
        return []
      },
    },
    //每一列的高度
    itemHeight: {
      type: Number,
      default: 30,
    },
    //顯示幾條資料
    showNum: {
      type: Number,
      default: 10,
    },
  },
  data () {
    return {
      start: 0, //滾動過程顯示的開始索引
      end: 10, //滾動過程顯示的結束索引
      offset: 0, //前置隱藏偏移
      offset_top: 0, // 整體偏移
      boxH: 0, // 容器高度
      barH: 0 // 原始高度,即將列表全部渲染後的高度
    }
  },
  computed: {
    //顯示的陣列,用計算屬性計算
    visibleData () {
      let start = this.start - this.prevCount
      let end = this.end + this.nextCount
      return this.dataList.slice(start, end)
    },
    //前面預留幾個 為了放置空白現象
    prevCount () {
      return Math.min(this.start, this.showNum)
    },
    //後面預留幾個
    nextCount () {
      return Math.min(this.showNum, this.dataList.length - this.end)
    },
  },
  mounted () {
    this.initData()
  },
  methods: {
    // 資料長度長度改變時呼叫
    initData () {
      //當前的一項高度*顯示的專案高度
      this.boxH = this.itemHeight * this.showNum
      //當前總長度*當前的專案高度
      setTimeout(() => {
        this.barH = this.dataList.length * this.itemHeight
      })
    },
    // 滾動事件
    scrollListener () {
      //獲取滾動高度
      let scrollTop = this.$refs.viewport.scrollTop
      //開始的陣列索引
      this.start = Math.floor(scrollTop / this.itemHeight)
      //結束索引
      this.end = this.start + this.showNum
      //絕對定位對相對定位的偏移量
      this.offset_top = this.start * this.itemHeight
      this.offset = 0 - this.prevCount * this.itemHeight
    },
    // 跳轉到指定位置
    setRate (rate) {
      this.start = rate
      this.$refs.viewport.scrollTop = this.start * this.itemHeight
      this.end = this.start + this.showNum
      this.offset_top = this.start * this.itemHeight
      this.offset = 0 - this.prevCount * this.itemHeight
    }
  },
}
</script>
    <style>
.viewport {
  overflow-y: scroll;
  position: relative;
}
.scroll-list {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
}
</style>