当面试官问你:怎么处理百万条数据渲染的性能问题?

不要再回答使用分页或者文档碎片了

回答分页 ,不是很贴切考官的问题,考官也不会想听到这样的答案,
第二 ,文档碎片 ,这是使用js 操作dom 的时候需要用到,需要动态生成原生dom,在vue的项目里使用比较不方便。能回答到这个勉强可以。

我推荐的是:window.requestAnimationFrame
requestAnimationFrame是HTML5中提供的动画API,简称rAF,即请求动画帧。可以让浏览器优化并行的动画动作,更合理的重新排列动作序列,并把能够合并的动作放在一个渲染周期内完成,从而呈现出更流畅的动画效果。

浏览器每次渲染一秒钟渲染60次 1000ms/60s , 即 每毫秒16.6次 。
当我们页面的数据超级多的时候,一次性就渲染全部的数据,就会造成页面卡顿
我们来看下一个例子:


image.png

右边是渲染的dom 每个div盒子里面包含了n个div块,数量其实并不多。但是等待页面却花了十秒钟的时间
通过性能调试面板可以看到 浏览器装载只需要1毫秒 执行js 脚本花了 5秒多 ,渲染也花了四秒多,总计 10秒左右。


image.png

看看代码如何写的,可以看到就是嵌套了两个循环一个 ,两个循环一百次 ,总的差不多是百万循环了,js一次性就加载,是需要十秒,这个时候浏览器是一直白屏的,需要等待差不多九秒,页面才出来东西

image.png

看看使用了 requestAnimationFrame 优化之后 前后对比,速度不是一般的快.

实际上就是 浏览器分开渲染,n毫秒内渲染前面几个div盒子。一直在渲染,直到渲染完毕。相当是把十秒钟拆分成每一秒渲染前多少个div,以此类推。这样用户一进来就能看到前半段的东西,剩余的浏览器会慢慢加载,并不会影响前面的显示,这样一样来就能解决这种性能的问题,也不会影响用户体验。


image.png

完整的代码示例

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

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>defer</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }

        .box {
            width: 100vw;
            height: 100vh;
            display: flex;
            flex-wrap: wrap;
        }

        .block {
            width: 400px;
            margin: 20px;
            height: 400px;
            border: 1px solid red;
            display: flex;
            flex-wrap: wrap;
        }

        .item {
            width: 6px;
            height: 6px;
            background: #000;
            margin: 1px;
        }
    </style>
</head>

<body>
    <div id="app" class="box">
        <template v-for="(item,index) in 1000">
             <!-- 默认显示优化后的代码 -->
            <!-- 使用没有用requestAnimationFrame优化之前的渲染代码可以将v-if="defer(index)" 删掉即可 -->
            <div class="block" v-if="defer(index)">
                <div class="item" v-for="(sub,index) in 1000"></div>
            </div>
        </template>
    </div>
</body>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.2.6/vue.js"></script>
<script>
    new Vue({
        el: '#app',
        data() {
            return {
                frameCount: 0,
            }
        },
        mounted() {
            const refreshFrameCount = (maxFrameCount) => {
                requestAnimationFrame(() => {
                    this.frameCount++
                    if (this.frameCount < maxFrameCount) {
                        refreshFrameCount(maxFrameCount)
                    }
                })
            }
            refreshFrameCount(500)
        },
        methods: {
            defer(showInFrameCount) {
                return this.frameCount >= showInFrameCount
            }
        }
    })
</script>

</html>
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。