<template> <div class="viewport" @scroll="scroll"> <div class="list-phantom" :style="{height: totalHeight+'px'}"></div> <div class="list-area" :style="{transform: `translate3d(0,${startOffset}px,0)`}"> <div v-for="item in viewData" :key="item" class="list-item" :style="{height: height+'px',lineHeight: height+'px'}">{{item}}</div> </div> </div> </template> <script> export default { data(){ return { list: [], height: 100, startIndex: 0, scrollTop: 0 } }, created(){ for (let i = 0; i < 1000; i++) { this.list.push(i); } this.totalHeight = this.list.length * this.height }, computed: { endIndex(){ return this.startIndex + 10 }, viewData(){ return this.list.slice(this.startIndex,this.endIndex) }, startOffset(){ return this.startIndex*this.height } }, methods: { scroll(e){ this.scrollTop = e.target.scrollTop this.startIndex = Math.floor(this.scrollTop / this.height) } } } </script> <style> .viewport { height: 100vh; overflow: scroll; position: relative; } .list-phantom { position: absolute; top: 0; left: 0; width: 100%; } .list-item { color: #555; text-align: center; box-sizing: border-box; border-bottom: 1px solid #999; } </style>