重绘和回流 及减少重绘和回流的方式

Posted 奥特曼 

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了重绘和回流 及减少重绘和回流的方式相关的知识,希望对你有一定的参考价值。

重绘和回流是前端经常听到的一个概念,这就涉及到了从html代码到浏览器的一个渲染过程。

我们还听到过一个概念叫重排,其实和回流是一个意思。

(1)前景

从浏览器的渲染引擎开始,首先会将HTML文档解析成 DOM Tree,与此同时,会将CSS文档解析成CSSOM,最后进行一个拼接,拼接成render Tree

(2)重绘

重绘,就像涂色一样,只修改一个元素的颜色,并不修改它的结构,就是重绘。

(3)回流/重排

当元素的宽高大小、隐藏显示,只要涉及到影响网页的布局就会触发回流,触发回流的同时必定引起重绘,但重绘不会引起回流。

在浏览器第一次加载时,就会产生一次回流 这也是开销非常大的。

触发回流

1.浏览器第一次加载

2.元素隐藏、显示

3.改变元素大小

4.元素位置发生改变

总结:只要不影响布局 只影响 元素颜色都会触发重绘,只要影响布局就会触发回流,触发回流的同时也会触发重绘

减少触发回流重绘的方式

(1)当用js代码多次修改结构样式时,每一行js代码都会产生一次回流(特指修改样式结构),不如添加一个类 用类名去控制样式。(包括用css一条一条修改样式结构)

(2)避免使用表格 修改一行表格的大小时 其他行、列的大小也会受影响

(3)复杂动画效果,使用绝对定位让其脱离文档流 

(4)用transform:translate 代替 position  left、right...

场景 两秒后移动元素的位置,首先用 定位 再用transform

    <style>
        div {
            width: 100px;
            height: 100px;
            background: pink;
            position: absolute;
        }
    </style>
</head>
<div></div>
<body>
    <script>
        let div = document.querySelector('div')
        setTimeout(() => {
            div.style.left=100+'px'
        }, 2000);
    </script>
</body>

发现 2秒左右时触发了 重排和重绘 接下来再看 transform 

    <style>
        div {
            width: 100px;
            height: 100px;
            background: pink;
            transform: translateX(0);
        }
    </style>
</head>
<div></div>
<body>
    <script>
        let div = document.querySelector('div')
        setTimeout(() => {
            div.style.transform='translateX(100px)'
        }, 2000);
    </script>
</body>

这次再来看 发现 没有触发 重排和重绘,这也是transform动画是由GPU控制的,GPU是在组合线程上执行的,而其他是在主线程执行的,主线程执行会将页面绘制成一张位图或多张位图发送给组合线程,而组合线程会将主线程上的位图显示出来。

(5)离线后修改 一开始先隐藏 给样式都修改完后 在显示出来

(6)避免循环DOM元素  每次渲染一次DOM就会发生重绘重排一次

(7)利用文档碎片添加元素 (DocumentFragment不是真实的DOM,不会每次触发渲染,可以理解为 可以将所有的DOM进行收集起来,最后直接插入到浏览器中)

<body>
    <ul class="list"></ul>
    <script>
        const list = document.querySelector('.list')
        const fruits = ['A','B','C','D']
        const fragment = document.createDocumentFragment()
        fruits.forEach(fruit=>{
            const li = document.createElement('li')
            li.innerHTML=fruit
            fragment.appendChild(li)
        })
        list.appendChild(fragment)
    </script>
</body>

以上是关于重绘和回流 及减少重绘和回流的方式的主要内容,如果未能解决你的问题,请参考以下文章

页面重绘和回流以及优化

灵魂拷问第6篇:谈谈你对重绘和回流的理解

重绘和回流

重绘和回流

重绘和回流的解释

Web APIs DOM 重绘和回流