<!doctype html><html lang="zh"><head> <meta charset="UTF -8"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <style> .container { width: 300px; height: 600px; overflow: auto; border: 1px solid; margin: 100px auto; } .item { height: 29px; line-height: 30px; border-bottom: 1px solid #aaa; padding-left: 20px; } </style></head><body> <div id="app"> <button @click="add">增加</button> <div class="container" ref="container"> <div class="scroll-wrapper" :style="style"> <div v-for="(item, index) in scrollList" :key="index" class="item">{{item}}</div> </div> </div> </div> <script crossorigin="anonymous" integrity="sha512-h3aCJRk6tEHugDYUidF7GqixhzgeXSiSdq5U+5oLIJtIncSQq6eev48qqYfuTdrsH5Q1eO4IAmyJGDwzRaWNNQ==" src="https://lib.baomitu.com/vue/2.6.12/vue.common.dev.js"></script> <script> new Vue({ el: '#app', data: { list: [ '测试数据' ], startIndex: 0, endIndex: 60, paddingTop: 0, paddingBottom: 0, allHeight: 0 }, computed: { scrollList() { return this.list.slice(this.startIndex, this.endIndex) }, style() { return { paddingTop: this.paddingTop + 'px', paddingBottom: this.paddingBottom + 'px' } } }, watch: { list(val) { const valLen = val.length this.allHeight = valLen * 30 this.paddingBottom = this.allHeight - this.scrollList.length * 30 } }, mounted() { const container = this.$refs.container container.addEventListener('scroll', () => { const top = container.scrollTop this.startIndex = Math.floor(top / 30) this.endIndex = this.startIndex + 60 this.paddingTop = top if (this.endIndex >= this.list.length - 1) { this.paddingBottom = 0 return } this.paddingBottom = this.allHeight - 600 - top }) }, methods: { add() { let arr = new Array(100).fill(0) arr = arr.map((item, index) => { return index }) this.list = [ ...this.list, ...arr ] } } }) </script></body></html>