虚拟列表

188 阅读1分钟
<!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 src="./vue.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>