JavaScript頁面回流與重繪
1.DOMAPI
1.1獲取元素相關(guān)結(jié)點(diǎn)API
<body> ?? ?<div class="item"> ?? ??? ?<h3 class="title">123</h3> ?? ??? ?<p class="des">456</p> ?? ??? ?<p class="price">789</p> ?? ?</div> ?? ?<script> ?? ??? ?var oItem = document.querySelector(".item"); ?? ??? ?var oTitle = oItem.querySelector("h3"); ?? ??? ?var itemChild = oItem.children;//獲取當(dāng)前對象的所有子元素,并且以集合的形式返回 ?? ??? ?console.log(itemChild); ?? ??? ?console.log(oItem.childNodes);//獲取元素內(nèi)的節(jié)點(diǎn)列表,注意,換行符也會被當(dāng)做是一個(gè)文本節(jié)點(diǎn) ?? ??? ?console.log(oItem.firstChild);//獲取元素第一個(gè)子(節(jié)點(diǎn):標(biāo)簽和文本) ?? ??? ?console.log(oItem.firstElementChild);//獲取元素第一個(gè)子元素(只指代標(biāo)簽 ?不包括文本節(jié)點(diǎn)) ?? ??? ?console.log(oItem.lastChild);//獲取元素最后一個(gè)子(節(jié)點(diǎn):標(biāo)簽和文本) ?? ??? ?console.log(oItem.lastElementChild);//獲取元素最后一個(gè)子元素(只指代標(biāo)簽 ?不包括文本節(jié)點(diǎn)) ?? ??? ?//Node節(jié)點(diǎn) ?Element元素 ?? ??? ?console.log(oTitle.parentElement);//獲取元素父元素 ?? ??? ?console.log(oTitle.parentNode);//也是獲取父元素 ?? ??? ?console.log(oTitle.nextElementSibling);//下一個(gè)兄弟元素 ?? ??? ?console.log(oTitle.nextSibling);//下一個(gè)兄弟節(jié)點(diǎn)(包含文本節(jié)點(diǎn)) ?? ??? ?console.log(oTitle.previousElementSibling);//上一個(gè)兄弟元素 ?? ??? ?console.log(oTitle.previousSibling);//上一個(gè)兄弟節(jié)點(diǎn)(包含文本節(jié)點(diǎn)) ?? ?</script> </body>
1.2增加節(jié)點(diǎn)API
<script> ?? ?var oWrap = document.createElement("div"); ?? ?//參數(shù)是tagName,也就是標(biāo)簽名稱 ?? ?oWrap.className = "wrap";//添加類名 ?? ?oWrap.innerText = "文本";//添加一些文本 ?? ?oWrap.style.fontSize = "30px";//設(shè)置字體大小 ?? ?oWrap.style.color = "red";//設(shè)置顏色 ?? ?//向body里添加標(biāo)簽 ?? ?document.body.appendChild(oWrap); ?? ?//向添加的div標(biāo)簽里再添加一個(gè)p標(biāo)簽 ?? ?var oP = document.createElement("p"); ?? ?oP.innerText = "我是p標(biāo)簽"; ?? ?oWrap.appendChild(oP); ?? ?//用innerHTML來添加節(jié)點(diǎn) ?? ?var elementStr = '<div class="erao"><p style="color: red; font-size: 30px;">我是p是wrap的子元素</p></div>'; ?? ?document.body.innerHTML = elementStr; ?? ? </script>
2.回流與重繪
2.1CSS的書寫順序影響
示例:
?span { ? ? ? width: 200px; ? ? ? height: 200px; ? ? ? margin: 10px; ? ? ? border: 2px solid red; ? ? ? background-color: #368; ? ? }
如上的css代碼,在HTML頁面中span標(biāo)簽不會被渲染出來,這是因?yàn)閟pan標(biāo)簽是行級元素,不能設(shè)定width
和height
值,如果我們在最下面寫一行position: absolute
;,這就會導(dǎo)致瀏覽器切換計(jì)算模式。
瀏覽器在讀css代碼時(shí)是從上而下一行一行代碼讀的,在沒有讀到這行代碼時(shí)瀏覽器先是用的行級元素的計(jì)算模式來閱讀這段css代碼,當(dāng)讀到position: absolute;
這行代碼時(shí)
瀏覽器隱式的將span的display
展示模式更改為block,自然也將計(jì)算模式切換成塊級元素的計(jì)算模式,然后再從頭讀這段css代碼,渲染。
2.2節(jié)點(diǎn)渲染優(yōu)化
一個(gè)html頁面是一個(gè)整體,當(dāng)這個(gè)整體中的某一個(gè)部分發(fā)生改變,那么這個(gè)頁面整體會重新進(jìn)行渲染,而如果我們采用添加標(biāo)簽的方式,每次添加一個(gè)標(biāo)簽,就會讓每一次頁面都重新渲染,性能急劇下降
解決方法是:使用Fragment
臨時(shí)容器
示例:
drawDom(3000, 'div'); ? ? function drawDom(num, tagName) { ? ? ? var vDom; ? ? ? for (var i = 0; i < num; i++) { ? ? ? ? vDom = document.createElement(tagName); ? ? ? ? document.body.appendChild(vDom); //重復(fù)N次 每次渲染一個(gè)標(biāo)簽 ? ? ? } ? ? }
如上述代碼,當(dāng)我們一個(gè)一個(gè)渲染3000個(gè)標(biāo)簽的時(shí)候,在本地的頁面打開都需要一秒多,如果是線上的,那性能更加差
所以我們要使用Fragement
臨時(shí)容器,如果說頁面渲染相當(dāng)于貨架上的商品,那么appendChild
方法就相當(dāng)于每一次從工廠生產(chǎn)商品立刻送到商店擺上貨架,每一次都需要重新編排商品。
而使用Fragement
時(shí),就相當(dāng)于在工廠和貨架之間放置了一個(gè)大箱子,工廠生產(chǎn)出賴商品后先將商品放置在Fragment
里,當(dāng)需要的商品數(shù)量生產(chǎn)完后,再將Fragement這個(gè)大箱子直接提到商店,將里面的商品一次性擺上貨架,這時(shí)就只需要編排一次商品,大大的提升了渲染性能。
修改后的代碼:
drawDom(3000, 'div'); ? ? function drawDom(num, tagName) { ? ? ? var vDom; ? ? ? var fragment = document.createDocumentFragment();//文檔片段 ? ? ? for (var i = 0; i < num; i++) { ? ? ? ? vDom = document.createElement(tagName); // ? ? ? ? fragment.appendChild(vDom); //放到臨時(shí)容器fragment里 ? ? ? } ? ? ? document.body.appendChild(fragment); ?//一次渲染渲染N個(gè) ? ? }
這里要注意innerHTML
也會有同樣的問題,解決的方式就是不要用innerHTML來每一次改變,而是以一個(gè)字符串來進(jìn)行改變,等所有的改變結(jié)束后再直接賦值給innerHTML,也是能大大提升性能的
示例:
?drawHtml(3000, 'div'); ?function drawHtml(num, tagName) { ? ? ? var eleStr = ''; ? ? ? for (var i = 0; i < num; i++) { ? ? ? ? eleStr += '<' + tagName + '></' + tagName + '>'; ? ? ? } ? ? ? document.body.innerHTML = eleStr; }
到此這篇關(guān)于JavaScript頁面回流與重繪的文章就介紹到這了,更多相關(guān)JavaScript頁面回流與重繪內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
es6學(xué)習(xí)之解構(gòu)時(shí)應(yīng)該注意的點(diǎn)
解構(gòu)賦值允許你使用類似數(shù)組或?qū)ο笞置媪康恼Z法將數(shù)組和對象的屬性賦給各種變量。這種賦值語法極度簡潔,同時(shí)還比傳統(tǒng)的屬性訪問方法更為清晰,下面這篇文章主要給大家介紹了關(guān)于在es6解構(gòu)時(shí)應(yīng)該注意的點(diǎn),需要的朋友可以參考下。2017-08-08laydate 顯示結(jié)束時(shí)間不小于開始時(shí)間的實(shí)例
下面小編就為大家?guī)硪黄猯aydate 顯示結(jié)束時(shí)間不小于開始時(shí)間的實(shí)例。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-08-08JavaScript如何調(diào)用C++模塊中的函數(shù)
這篇文章主要給大家介紹了關(guān)于JavaScript如何調(diào)用C++模塊中函數(shù)的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2024-01-01javascript移出節(jié)點(diǎn)removeChild()使用介紹
這篇文章主要介紹了javascript節(jié)點(diǎn)操作移出節(jié)點(diǎn)removeChild()的使用,需要的朋友可以參考下2014-04-04解決IE下select標(biāo)簽innerHTML插入option的BUG(兼容IE,FF,Opera,Chrome,Safa
在ie下面使用innerHTML來插入option選項(xiàng)的話,ie會去掉前面的<option>,并拆分成多個(gè)節(jié)點(diǎn),這樣會造成select的出錯(cuò)2010-05-05