去聽了牛人 dbaron 的一個(gè) Web Page Layout/Display in Mozilla 講座( via )。講的東西對(duì)我一個(gè)只會(huì)HTML, CSS和JavaScript的人來說很底層,所以效果也比較“和諧”,只是大致了解了mozilla的CSS渲染源碼分布位置和渲染流程而已。
講座提到了reflow(如何翻譯呢?又是一個(gè)問題)這個(gè)東東。之前對(duì)reflow有所聞,能經(jīng)常從某些大牛的幻燈中提到,提高頁(yè)面渲染的性能,需盡量避免reflow. 那么reflow是什么東西呢?它又是如何影響頁(yè)面性能的?事后去問了一下dbaron(呵呵,我口語(yǔ)徹底不行,加上心理素質(zhì),最后是把問題寫下來給他看),豁然開朗也。
在CSS規(guī)范中有一個(gè)渲染對(duì)象的概念,通常用一個(gè)盒子(box, rectangle)來表示。mozilla通過一個(gè)叫frame的對(duì)象對(duì)盒子進(jìn)行操作。frame主要的動(dòng)作有三個(gè):
- 構(gòu)造frame, 以建立對(duì)象樹(DOM樹)
- reflow, 以確定對(duì)象位置,或者是調(diào)用mozilla的Layout(這里是指源碼的實(shí)現(xiàn))
- 繪制,以便對(duì)象能顯示在屏幕上
總的來說,reflow就是載入內(nèi)容樹(在HTML中就是DOM樹)和創(chuàng)建或更新frame結(jié)構(gòu)的響應(yīng)的一種過程。
要提高頁(yè)面性能,其實(shí)就是避免reflow的開銷。那么,有哪些方面是需要reflow的呢?比如,未指定圖片寬高的話,圖片的載入會(huì)使頁(yè)面reflow, 因?yàn)橐鶕?jù)圖片寬高來更新frame。這里就有一個(gè)提高頁(yè)面性能的小技巧:如果事先能夠確定圖片寬高的話,最好在HTML里寫上。
在編寫一些常見的動(dòng)態(tài)效果時(shí),一般使用CSS的display來切換可見性。很不幸,這也會(huì)產(chǎn)生reflow. 把元素置為display:none,相當(dāng)于把這個(gè)元素的frame銷毀了,再置回非none時(shí),需要重新構(gòu)造frame,這就產(chǎn)生了reflow. 而另外一個(gè)切換可見性的屬性visibility則不存在reflow問題,置為visibility:hidden的元素的frame并沒有銷毀,需要顯示的時(shí)候其實(shí)就是一個(gè)繪制(上面提到的動(dòng)作第三步)過程而已,沒有reflow,因此效率會(huì)更高。如果你看過一些JavaScript庫(kù)/框架的源碼,會(huì)發(fā)現(xiàn)它們大量使用visibility而不是display,道理應(yīng)該如此。