效果图
<template><!-- 总体高度区域 --><divref="listWrap"class="m-container"@scroll="scrollListener"><div:style="handleContainerHeight()"><!-- 可视区域 --><divclass="m-area":style="handleAreaStyle()"><divv-for="(item,index) in displayList":key="index":style="handleItemStyle()">{{ item.name }}</div></div></div></div>
</template>
<script lang="ts">
import { Options, Vue } from 'vue-class-component';
interface ListType {label: string;value: string;
}
@Options({props: {list: {default:[],},},
})
export default class MList extends Vue {list!: ListType[];/** 每行高度 */itemSize = 100;/** 一次性展示多少个数据 */showNum = 10;/** 开始下标 */start =0;/** 结束下标 */end = 10;/** 滚动位置 */scrollTop = 0;get displayList() {const arr = this.list.slice(this.start,this.end);if(arr.length) {return arr;}return [];}handleItemStyle() {return {height: `${this.itemSize}px`,};}handleContainerHeight() {return {height: this.list.length * this.itemSize + 'px',};}handleAreaStyle() {return {'transform': `translateY(${this.scrollTop}px)`,};}scrollListener() {this.scrollTop = (this.$refs.listWrap.scrollTop as number);this.start = Math.floor(this.scrollTop/this.itemSize);this.end = this.start + this.showNum;}}
</script>
<style scoped>
.m-container {height: 100vh;overflow: auto;
}
</style>