zoukankan      html  css  js  c++  java
  • 性能优化:虚拟列表,如何渲染10万条数据的dom,页面同时不卡顿

    最近做的一个需求,当列表大概有2万条数据,又不让做成分页,如果页面直接渲染2万条数据,在一些低配电脑上可能会照成页面卡死,基于这个需求,我们来手写一个虚拟列表

    思路

    1. 列表中固定只显示少量的数据,比如60条
    2. 在列表滚动的时候不断的去插入删除dom
    3. startIndex、endIndex,不断的改变这个值来获取最新的显示列表
    4. paddingTop、paddingBottom撑开容器的滚动区域

    首先看一下当直接插入2万条列表时,页面的性能

    可以看到火焰图中已经有了红色的部分了,dom渲染也耗时也有1s多

    再来看一下当使用虚拟列表时页面的性能

    从火焰图中可以看出,火焰图中一篇绿油油的,这就证明,通过虚拟列表来进行渲染使页面性能得到了极大的提升

    简单的虚拟列表demo实现

    我们假设有一个容器,高度为600px,列表项每个高度为30px,那么根据列表的length我们就可以计算出滚动容器的总高度,也可以知道显示60条数据的高度,我们此时可以给容器加一个paddingBottom,来撑开容器,来模拟页面应该滚动的高度

    this.paddingBottom = this.allHeight - this.scrollList.length * 30
    

    容器同时还需要paddingTop用做当容器滚动顶部数据移除后撑起scrollTop

    最后我们需要监听容器的滚动事件来不断的修改paddingTop、paddingBottom、startIndex、endIndex

    最终效果

    最后附上所有代码

    <!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 {
                 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 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(50000).fill(0)
                    arr = arr.map((item, index) => {
                        return index
                    })
                    this.list = [
                        ...this.list,
                        ...arr
                    ]
                }
            }
        })
    </script>
    </body>
    </html>
    
    
  • 相关阅读:
    springmvc之异常处理DefaultHandlerExceptionResolver
    springmvc之异常处理ResponseStatusExceptionResolver
    springmvc之异常处理中ExceptionHanderExceptionResolver
    springmvc之多个拦截器方法执行的顺序
    springmvc之配置拦截器拦截相应的请求
    springmvc之自定义拦截器
    springmvc之文件上传
    springmvc之HttpMessageConverter<T>
    构建Java并发模型框架
    Java线程:线程的调度-守护线程——Java线程:线程的调度-合并——Java线程:新特征-障碍器——Java线程:大总结
  • 原文地址:https://www.cnblogs.com/songbw/p/11613869.html
Copyright © 2011-2022 走看看