基于vue2做定高虚拟列表滚动

576 阅读1分钟

Talk is cheap, show code!

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .list-wrap {
            position: relative;
            overflow-y: scroll;
            width: 200px;
            margin: 100px auto;
            box-sizing: border-box;
            border: solid 1px red;
        }

        .list {
            position: absolute;
            top: 0;
            left: 0;
        }

        .list li {
            border: solid 1px blue;
            line-height: 30px;
        }
    </style>
</head>

<body>
    <ul id="app">
        <div class="list-wrap" ref="listWrap" @scroll="scrollListener">
            <div class="scroll-bar" ref="scrollBar"></div>
            <ul class="list" ref="list">
                <li v-for="val in showList">{{val}}</li>
            </ul>
        </div>
    </ul>
    <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.14/vue.common.dev.js"></script>
    <script>
        new Vue({
            el: '#app',
            data() {
                return {
                    listWrapElem: null,
                    scrollBarElem: null,
                    listElem: null,
                    list: [],//超长的显示数据
                    itemHeight: 30,//每一列的高度
                    showNum: 10,//显示几条数据
                    start: 0,//滚动过程显示的开始索引
                    end: 10,//滚动过程显示的结束索引
                }
            },
            computed: {
                //显示的数组,用计算属性计算
                showList() {
                    return this.list.slice(this.start, this.end);
                }
            },
            mounted() {
                //构造一个超长列表
                for (let i = 0; i < 10000; i++) {
                    this.list.push('列表' + i)
                }
                this.listWrapElem = this.$refs.listWrap
                this.scrollBarElem = this.$refs.scrollBar
                this.listElem = this.$refs.list
                //计算滚动容器高度
                this.listWrapElem.style.height = this.itemHeight * this.showNum + 'px';
                //计算总的数据需要的高度,构造滚动条高度
                this.scrollBarElem.style.height = this.itemHeight * this.list.length + 'px';

            },
            methods: {
                scrollListener() {
                    //获取滚动高度
                    let scrollTop = this.listWrapElem.scrollTop;
                    //开始的数组索引
                    this.start = Math.floor(scrollTop / this.itemHeight);
                    //结束索引
                    this.end = this.start + this.showNum;
                    //绝对定位对相对定位的偏移量
                    this.listElem.style.top = this.start * this.itemHeight + 'px';
                }
            }
        })
    </script>
</body>

</html>