vue長列表渲染元件
阿新 • • 發佈:2021-12-23
<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>