摘要:優(yōu)化的本質(zhì)其實(shí)就是減少樹(shù)的重流與重繪。對(duì)于重流和重繪的理解,詳見(jiàn)前端知識(shí)普及之優(yōu)化的結(jié)構(gòu),無(wú)非就是引用保存,動(dòng)畫(huà)優(yōu)化,節(jié)點(diǎn)保存,更新節(jié)點(diǎn)等基本操作。那重繪什么時(shí)候會(huì)發(fā)生呢發(fā)生重流就一定會(huì)發(fā)生重繪,但是,重繪的范圍比重流稍微大了一點(diǎn)。
優(yōu)化DOM的本質(zhì)其實(shí)就是減少DOM樹(shù)的重流與重繪。對(duì)于重流和重繪的理解,詳見(jiàn)《前端知識(shí)普及之HTML》
優(yōu)化DOM的結(jié)構(gòu),無(wú)非就是引用保存,動(dòng)畫(huà)優(yōu)化,節(jié)點(diǎn)保存,更新節(jié)點(diǎn)等基本操作。
曾記得,以前在網(wǎng)上翻閱HTML的時(shí)候,很多人都會(huì)不約而同(兒童)的說(shuō)道,獲取到DOM節(jié)點(diǎn)后一定要記得保存。否則,下場(chǎng)很難看的。
為什么~為什么~為什么~
我們都知道所謂的js其實(shí)是DOM,BOM,ECMA結(jié)合的產(chǎn)物。 本來(lái)我js挺快的,你非要去的DOM說(shuō)說(shuō)話(huà)。 那怎么辦,只有敲敲門(mén),等DOM來(lái)回應(yīng)你呀~ 但是,這個(gè)等待時(shí)間灰常長(zhǎng)。
看個(gè)demo吧.
var times=10000; var time1 = function(){ var time = times; while(time--){ //DOM的兩個(gè)操作放在循環(huán)內(nèi) var dom = document.querySelector("#Div1"); dom.innerHTML+="a"; } }; var time2=function(){ var time = times, dom = document.querySelector("#Div1"); while(time--){ //DOM的一個(gè)操作放在循環(huán)內(nèi) dom.innerHTML+="a"; } }; var time3=function(){ var time = times, dom = document.querySelector("#Div1"), str = ""; while(time--){ //循環(huán)內(nèi)不放置DOM的操作 str +="a"; } dom.innerHTML=str; } console.time(1); //設(shè)置時(shí)間起點(diǎn) time1(); console.timeEnd(1); console.time(2); //設(shè)置時(shí)間起點(diǎn) time2(); console.timeEnd(2); console.time(3); //設(shè)置時(shí)間起點(diǎn) time3(); console.timeEnd(3); //測(cè)試結(jié)果為: 1: 101.868ms 2: 101.560ms 3: 13.615ms
當(dāng)然,這只是個(gè)比較夸張的例子了,當(dāng)你過(guò)多的頻繁操作DOM的時(shí)候,一定要記得保存。 而且,保存一定是要保存所有涉及DOM相關(guān)的操作。
比如. style,innerHTML等屬性。
而這樣做的原理就是減少重流和重繪的次數(shù)。
那重流和重繪通常什么情況下會(huì)發(fā)生呢?
重流發(fā)生情況:
添加或者刪除可見(jiàn)的DOM元素
元素位置改變
元素尺寸改變
元素內(nèi)容改變(例如:一個(gè)文本被另一個(gè)不同尺寸的圖片替代)
頁(yè)面渲染初始化(這個(gè)無(wú)法避免)
瀏覽器窗口尺寸改變
總的來(lái)說(shuō),就是改變頁(yè)面的布局,大小,都會(huì)發(fā)生重流的情況。
那重繪什么時(shí)候會(huì)發(fā)生呢? 發(fā)生重流就一定會(huì)發(fā)生重繪,但是,重繪的范圍比重流稍微大了一點(diǎn)。比如,當(dāng)你僅僅改變字體顏色,頁(yè)面背景顏色等 比較"膚淺"的操作時(shí),是不會(huì)打擾到重排的。
當(dāng)我們這樣操作時(shí):
div.style.color="red"; div.style.border="1px solid red";
瀏覽器會(huì)很聰明的將兩次重排合并到一次發(fā)生,節(jié)省資源。 其實(shí)函數(shù)節(jié)流的思想和這個(gè)有異曲同工的妙處
var throttle = (function(){ var time; return function(fn,context){ clearTimeout(time); //進(jìn)行函數(shù)的節(jié)流 time = setTimeout(fn.bind(context),200); } })()
這個(gè)技巧通常用在你調(diào)整瀏覽器大小的時(shí)候。
但是,如果中間,你訪(fǎng)問(wèn)了offsetTop,clientTop等 立即執(zhí)行屬性的話(huà)。那結(jié)果你就么么噠了。
div.style.color="red"; //積累一次重排記錄 var height = div.clientHeight; //觸發(fā)重排 div.style.border="1px solid red"; //再次積累一次重排
這時(shí)候,瀏覽器已經(jīng)被你玩傻了。 所以,給的一點(diǎn)建議就是,如果要更改DOM結(jié)構(gòu)最好一次性整完,或者,要整一起整~
我們上面的css修改,還可以這樣
div.style.cssText="color:red;border:1px solid red"; //覆蓋原來(lái)的css div.classList.add("change"); //利用class來(lái)整體改動(dòng)DOM操作的優(yōu)化
DOM的操作無(wú)非就CRUD。
這里簡(jiǎn)單說(shuō)一下基本的API
var div = document.createELement("div");查找節(jié)點(diǎn)
var divs = document.querySelectorAll("div"); //很多個(gè),放在數(shù)組內(nèi) var onlydiv = document.querySelector("div"); //只有一個(gè) //以及document.getElement系列查看節(jié)點(diǎn)
var html = div.innerHTML; var outer = div.outerHTML; //這兩個(gè)是非常常用的 var classNames = div.classList; var className = div.className; var tagName = div.tagName; var id = div.id; var style = div.getAttribute("style"); //....移動(dòng)節(jié)點(diǎn)
ele.replaceChild(replace,replaced); //replace代替replaced //添加子節(jié)點(diǎn) ele.appendChild(child); //刪除子節(jié)點(diǎn) ele.removeChild(child); //插入子節(jié)點(diǎn) ele.insertBefore(newEle,referenceEle);
Ok~ 其實(shí),上面所說(shuō)的這些API只要涉及到DOM操作的都會(huì)發(fā)生重排。所以,這里是地方可以?xún)?yōu)化的.
使用fragment當(dāng)我們需要批量加入子節(jié)點(diǎn)的時(shí)候,就需要使用fragment這個(gè)虛擬片斷,來(lái)作為一個(gè)容器.
比如,我們需要在div里面添加100個(gè)p標(biāo)簽
var times = 100; var addP = function(){ var time = times, tag1 = document.querySelector("#tag1"); while (time--) { var p = document.createElement("p"); tag1.appendChild(p); } } var useFrag = function(){ var time = times, tag1 = document.querySelector("#tag1"), frag = document.createDocumentFragment(); while (time--) { var p = document.createElement("p"); frag.appendChild(p); } tag1.appendChild(frag); } console.time(1); addP(); console.timeEnd(1); console.time(2); useFrag(); console.timeEnd(2); //基本事件差為: 1: 1.352ms 2: 0.685ms
除了使用fragment片斷,還可以使用innerHTML,outerHTML進(jìn)行相關(guān)的優(yōu)化操作。這里就不贅述了
UI操作的優(yōu)化這里想說(shuō)的其實(shí)不多,就是學(xué)會(huì)使用absolute排版。 因?yàn)楫?dāng)你進(jìn)行相關(guān)UI操作的時(shí)候,毫無(wú)疑問(wèn)有可能不經(jīng)意間,導(dǎo)致全屏的渲染。比如校園二手街的布局,當(dāng)你下滑的時(shí)候,他的headerbar便會(huì)發(fā)生擴(kuò)大,布局較差的情況是整版重排。(傻逼傻逼傻逼)
他這里不一樣,他直接使用absolute進(jìn)行布局,脫離了文檔流,防止頁(yè)面過(guò)度的重排,贊~
最后:
優(yōu)化之路漫漫,大家好自為之~
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/78704.html
摘要:提高代碼可讀性掌握這些就夠了今天看到一篇關(guān)于代碼優(yōu)化的文章寫(xiě)得十分實(shí)用在學(xué)習(xí)總結(jié)后梳理出思維結(jié)構(gòu)圖將收貨的分享一下原作者方應(yīng)杭原文地址注意這篇文章所指的代碼優(yōu)化特指的是代碼可讀性方面的一些寫(xiě)法優(yōu)化而不是指的性能優(yōu)化。 提高代碼可讀性,掌握這些就夠了 今天看到一篇關(guān)于代碼優(yōu)化的文章,寫(xiě)得十分實(shí)用,在學(xué)習(xí)總結(jié)后,梳理出思維結(jié)構(gòu)圖,將收貨的分享一下 原作者:方應(yīng)杭 原文地址:https://...
摘要:下面我們撇開(kāi)網(wǎng)絡(luò)方面的優(yōu)化,只分析靜態(tài)資源方面的優(yōu)化。不過(guò),也會(huì)阻止的構(gòu)建和延緩網(wǎng)頁(yè)渲染。未優(yōu)化正常加載優(yōu)化后異步加載根據(jù)上面的分析,我們可以清楚的認(rèn)識(shí)到,非必要優(yōu)先加載的,選擇異步加載是最優(yōu)選擇。 為什么做優(yōu)化 經(jīng)典問(wèn)題:白屏?xí)r間過(guò)長(zhǎng),用戶(hù)體驗(yàn)差產(chǎn)生的原因:網(wǎng)絡(luò)問(wèn)題、關(guān)鍵渲染路徑(CRP)問(wèn)題 怎么做優(yōu)化 如何做好優(yōu)化呢,網(wǎng)上隨便一搜,就有很多優(yōu)化總結(jié),無(wú)非就是網(wǎng)絡(luò)優(yōu)化、靜態(tài)資源(h...
摘要:下面我們撇開(kāi)網(wǎng)絡(luò)方面的優(yōu)化,只分析靜態(tài)資源方面的優(yōu)化。不過(guò),也會(huì)阻止的構(gòu)建和延緩網(wǎng)頁(yè)渲染。未優(yōu)化正常加載優(yōu)化后異步加載根據(jù)上面的分析,我們可以清楚的認(rèn)識(shí)到,非必要優(yōu)先加載的,選擇異步加載是最優(yōu)選擇。 為什么做優(yōu)化 經(jīng)典問(wèn)題:白屏?xí)r間過(guò)長(zhǎng),用戶(hù)體驗(yàn)差產(chǎn)生的原因:網(wǎng)絡(luò)問(wèn)題、關(guān)鍵渲染路徑(CRP)問(wèn)題 怎么做優(yōu)化 如何做好優(yōu)化呢,網(wǎng)上隨便一搜,就有很多優(yōu)化總結(jié),無(wú)非就是網(wǎng)絡(luò)優(yōu)化、靜態(tài)資源(h...
摘要:下面我們撇開(kāi)網(wǎng)絡(luò)方面的優(yōu)化,只分析靜態(tài)資源方面的優(yōu)化。不過(guò),也會(huì)阻止的構(gòu)建和延緩網(wǎng)頁(yè)渲染。未優(yōu)化正常加載優(yōu)化后異步加載根據(jù)上面的分析,我們可以清楚的認(rèn)識(shí)到,非必要優(yōu)先加載的,選擇異步加載是最優(yōu)選擇。 為什么做優(yōu)化 經(jīng)典問(wèn)題:白屏?xí)r間過(guò)長(zhǎng),用戶(hù)體驗(yàn)差產(chǎn)生的原因:網(wǎng)絡(luò)問(wèn)題、關(guān)鍵渲染路徑(CRP)問(wèn)題 怎么做優(yōu)化 如何做好優(yōu)化呢,網(wǎng)上隨便一搜,就有很多優(yōu)化總結(jié),無(wú)非就是網(wǎng)絡(luò)優(yōu)化、靜態(tài)資源(h...
閱讀 2929·2021-11-22 15:22
閱讀 20178·2021-09-22 15:00
閱讀 1533·2021-09-07 09:58
閱讀 1299·2019-08-30 13:01
閱讀 2512·2019-08-29 16:27
閱讀 2404·2019-08-26 13:25
閱讀 1684·2019-08-26 12:13
閱讀 1013·2019-08-26 11:53