JavaScript頁面回流與重繪
1.DOMAPI
1.1獲取元素相關結點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;//獲取當前對象的所有子元素,並且以集合的形式返回 console.log(itemChild); console.log(oItem.childNodes);//獲取元素內的節點列表,註意,換行符也會被當做是一個文本節點 console.log(oItem.firstChild);//獲取元素第一個子(節點:標簽和文本) console.log(oItem.firstElementChild);//獲取元素第一個子元素(隻指代標簽 不包括文本節點) console.log(oItem.lastChild);//獲取元素最後一個子(節點:標簽和文本) console.log(oItem.lastElementChild);//獲取元素最後一個子元素(隻指代標簽 不包括文本節點) //Node節點 Element元素 console.log(oTitle.parentElement);//獲取元素父元素 console.log(oTitle.parentNode);//也是獲取父元素 console.log(oTitle.nextElementSibling);//下一個兄弟元素 console.log(oTitle.nextSibling);//下一個兄弟節點(包含文本節點) console.log(oTitle.previousElementSibling);//上一個兄弟元素 console.log(oTitle.previousSibling);//上一個兄弟節點(包含文本節點) </script> </body>
1.2增加節點API
<script> var oWrap = document.createElement("div"); //參數是tagName,也就是標簽名稱 oWrap.className = "wrap";//添加類名 oWrap.innerText = "文本";//添加一些文本 oWrap.style.fontSize = "30px";//設置字體大小 oWrap.style.color = "red";//設置顏色 //向body裡添加標簽 document.body.appendChild(oWrap); //向添加的div標簽裡再添加一個p標簽 var oP = document.createElement("p"); oP.innerText = "我是p標簽"; oWrap.appendChild(oP); //用innerHTML來添加節點 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標簽不會被渲染出來,這是因為span標簽是行級元素,不能設定width
和height
值,如果我們在最下面寫一行position: absolute
;,這就會導致瀏覽器切換計算模式。
瀏覽器在讀css代碼時是從上而下一行一行代碼讀的,在沒有讀到這行代碼時瀏覽器先是用的行級元素的計算模式來閱讀這段css代碼,當讀到position: absolute;
這行代碼時
瀏覽器隱式的將span的display
展示模式更改為block,自然也將計算模式切換成塊級元素的計算模式,然後再從頭讀這段css代碼,渲染。
2.2節點渲染優化
一個html頁面是一個整體,當這個整體中的某一個部分發生改變,那麼這個頁面整體會重新進行渲染,而如果我們采用添加標簽的方式,每次添加一個標簽,就會讓每一次頁面都重新渲染,性能急劇下降
解決方法是:使用Fragment
臨時容器
示例:
drawDom(3000, 'div'); function drawDom(num, tagName) { var vDom; for (var i = 0; i < num; i++) { vDom = document.createElement(tagName); document.body.appendChild(vDom); //重復N次 每次渲染一個標簽 } }
如上述代碼,當我們一個一個渲染3000個標簽的時候,在本地的頁面打開都需要一秒多,如果是線上的,那性能更加差
所以我們要使用Fragement
臨時容器,如果說頁面渲染相當於貨架上的商品,那麼appendChild
方法就相當於每一次從工廠生產商品立刻送到商店擺上貨架,每一次都需要重新編排商品。
而使用Fragement
時,就相當於在工廠和貨架之間放置瞭一個大箱子,工廠生產出賴商品後先將商品放置在Fragment
裡,當需要的商品數量生產完後,再將Fragement這個大箱子直接提到商店,將裡面的商品一次性擺上貨架,這時就隻需要編排一次商品,大大的提升瞭渲染性能。
修改後的代碼:
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); //放到臨時容器fragment裡 } document.body.appendChild(fragment); //一次渲染渲染N個 }
這裡要註意innerHTML
也會有同樣的問題,解決的方式就是不要用innerHTML來每一次改變,而是以一個字符串來進行改變,等所有的改變結束後再直接賦值給innerHTML,也是能大大提升性能的
示例:
drawHtml(3000, 'div'); function drawHtml(num, tagName) { var eleStr = ''; for (var i = 0; i < num; i++) { eleStr += '<' + tagName + '></' + tagName + '>'; } document.body.innerHTML = eleStr; }
到此這篇關於JavaScript頁面回流與重繪的文章就介紹到這瞭,更多相關JavaScript頁面回流與重繪內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!