<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                [TOC] # 回流與重繪 回流:當render tree中的一部分(或全部)因為元素的規模**尺寸**,**布局**,**隱藏**等改變而需要重新構建。每個頁面至少需要一次回流,就是在頁面第一次加載的時候。在回流的時候,瀏覽器會使渲染樹中受到影響的部分失效,并重新構造這部分渲染樹,完成回流后,瀏覽器會重新繪制受影響的部分到屏幕中,該過程稱為重繪。 重繪:當render tree中的一些元素需要更新屬性,而這些屬性只是影響元素的外觀,風格,而不會影響布局的,比如background-color。 > 注意:回流必將引起重繪,而重繪不一定會引起回流。 > ![](https://box.kancloud.cn/d887cc6e05cce0a640f18d9a1ceafe65_720x357.png) * 藍色部分:HTML解析和網絡通信占用的時間 * 黃色部分:JavaScript語句執行所占用時間 * 紫色部分:重排占用時間 * 綠色部分:重繪占用時間 當頁面布局和幾何屬性改變時就需要回流。下述情況會發生瀏覽器回流: 1、添加或者刪除可見的DOM元素; 2、元素位置改變; 3、元素尺寸改變(margin、padding、border、width和height) 4、內容改變,尤其是輸入控件 5、頁面渲染初始化; 6、瀏覽器窗口尺寸改變(resize事件發生時); 7、改變文字大小; 8、激活偽類,如:hover; 9、offsetWidth, width, clientWidth, scrollTop/scrollHeight的計算, 會使瀏覽器將漸進回流隊列Flush,立即執行回流; 10、設置style屬性; ~~~ var s = document.body.style; s.padding = "2px"; // 回流+重繪 s.border = "1px solid red"; // 再一次 回流+重繪 s.color = "blue"; // 再一次重繪 s.backgroundColor = "#ccc"; // 再一次 重繪 s.fontSize = "14px"; // 再一次 回流+重繪 // 添加node,再一次 回流+重繪 document.body.appendChild(document.createTextNode('abc!')); ~~~ ## 回流的原因 瀏覽器在實現回流時,會遞歸地處理frame。 每個frame的回流都有一個原因, 這個原因會隨著frame逐級向下傳遞(傳遞過程中可能會改變)。 回流的原因決定了當前frame的回流行為,有這樣5種原因: * 初始化(Initial)。DOM載入后的第一次回流,將會遍歷所有frame。 * 漸進(Incremental)。當一個frame發生漸進回流時,意味著它前面的元素都沒有變, 而是它里面的元素變了。這會引起自底向上的作用。 * 改變大小(Resize)。元素的容器邊界發生變化時,此時元素內部狀態沒變。 在計算自頂向下的布局約束的同時,可以復用內部狀態。 * 樣式改變(StyleChange)。整個frame樹都應得到遍歷。 * Dirty。當一個容器已經緩存了多個子元素的Incremental回流時,該容器出于Dirty的狀態。 前面四種原因的回流都是在Presentation Shell中立即調用的, 而最后一種回流只有Incremental回流已經到達目標frame時才進行。 (因為這時自底向上的影響才被計算出來,才能決定容器的圖形顯示) # 重繪和回流和 Eventloop 有關 1. 當 Eventloop 執行完 Microtasks 后,會判斷`document`是否需要更新,因為瀏覽器是 60Hz 的刷新率,每 16.6ms 才會更新一次。 2. 然后判斷是否有`resize`或者`scroll`事件,有的話會去觸發事件,所以`resize`和`scroll`事件也是至少 16ms 才會觸發一次,并且自帶節流功能。 3. 判斷是否觸發了 media query 4. 更新動畫并且發送事件 5. 判斷是否有全屏操作事件 6. 執行`requestAnimationFrame`回調 7. 執行`IntersectionObserver`回調,該方法用于判斷元素是否可見,可以用于懶加載上,但是兼容性不好 8. 更新界面 9. 以上就是一幀中可能會做的事情。如果在一幀中有空閑時間,就會去執行`requestIdleCallback`回調。 以上內容來自于[HTML 文檔](https://link.juejin.im/?target=https%3A%2F%2Fhtml.spec.whatwg.org%2Fmultipage%2Fwebappapis.html%23event-loop-processing-model)。 # 如何減少回流、重繪 減少回流、重繪其實就是需要減少對render tree的操作(合并多次多DOM和樣式的修改),并減少對一些style信息的請求,盡量利用好瀏覽器的優化策略。具體方法有: 1. 直接改變className,如果動態改變樣式,則使用cssText(考慮沒有優化的瀏覽器) ~~~ // 不好的寫法 var changeDiv = document.getElementById('changeDiv'); changeDiv.style.color = '#093'; changeDiv.style.background = '#eee'; changeDiv.style.height = '200px'; // 比較好的寫法 div.changeDiv { background: #eee; color: #093; height: 200px; } document.getElementById('changeDiv').className = 'changeDiv'; ~~~ 2. 讓要操作的元素進行”離線處理”,處理完后一起更新 a) 使用DocumentFragment進行緩存操作,引發一次回流和重繪; b) 使用display:none技術(由于display屬性為none的元素不在渲染樹中,對隱藏的元素操作不會引發其他元素的重排。如果要對一個元素進行復雜的操作時,可以先隱藏它,操作完成后再顯示。這樣只在隱藏和顯示時觸發2次重排。); c) 使用cloneNode(true or false) 和 replaceChild 技術,引發一次回流和重繪; d) 將需要多次重排的元素,position屬性設為absolute或fixed; 3. 不要經常訪問會引起瀏覽器flush隊列的屬性,如果你確實要訪問,利用緩存 ~~~ // 不好的寫法 for(循環) { el.style.left = el.offsetLeft + 5 + "px"; el.style.top = el.offsetTop + 5 + "px"; } // 比較好的寫法 var left = el.offsetLeft, top = el.offsetTop, s = el.style; for (循環) { left += 10; top += 10; s.left = left + "px"; s.top = top + "px"; } ~~~ 4. 讓元素脫離動畫流,減少回流的Render Tree的規模 ~~~ $("#block1").animate({left:50}); $("#block2").animate({marginLeft:50}); ~~~ 5. 在內存中多次操作節點,完成后再添加到文檔中去。例如要異步獲取表格數據,渲染到頁面。可以先取得數據后在內存中構建整個表格的html片段,再一次性添加到文檔中去,而不是循環添加每一行。 7. 不要用tables布局的另一個原因就是tables中某個元素一旦觸發reflow就會導致table里所有的其它元素reflow。在適合用table的場合,可以設置table-layout為auto或fixed,這樣可以讓table一行一行的渲染,這種做法也是為了限制reflow的影響范圍。 參考資料 * [重繪,回流和合成,了解基本瀏覽器繪制幫你優化頁面性能](https://zhuanlan.zhihu.com/p/23428399) * [全新Chrome Devtool Performance使用指南](https://zhuanlan.zhihu.com/p/29879682) * [頁面重繪和回流以及優化](http://www.css88.com/archives/4996)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看