日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > asp.net >内容正文

asp.net

asp.net ajax 怎么获取前端ul li_字节前端提前批面试题:触发了几次回流几次重绘...

發(fā)布時間:2025/3/20 asp.net 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 asp.net ajax 怎么获取前端ul li_字节前端提前批面试题:触发了几次回流几次重绘... 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

一道字節(jié)面試題刷新了我的認(rèn)知,又學(xué)到了新知識,開心。

剛開始我說了答案是各3次,因?yàn)楂@取一次offsetWidth一次,然后改變樣式一次。

但是后來發(fā)現(xiàn)之所以offsetWidth會觸發(fā)重排是因?yàn)樗⑿落秩娟?duì)列。而在這道題中,之前的渲染隊(duì)列為空,所以不會觸發(fā)重排。所以兩次。

后面發(fā)現(xiàn)又錯了,是因?yàn)橛袖秩娟?duì)列,所以因該是一次。不懂渲染隊(duì)列沒關(guān)系,往下看,就懂了。

當(dāng)然要分為古董瀏覽器和現(xiàn)代瀏覽器。現(xiàn)代瀏覽器(也就是說有渲染隊(duì)列的)應(yīng)當(dāng)是一次,古董的應(yīng)當(dāng)是2次

一.什么是重繪與重排

瀏覽器下載完頁面中的所有組件——HTML標(biāo)記、JavaScript、CSS、圖片之后會解析生成兩個內(nèi)部數(shù)據(jù)結(jié)構(gòu)——DOM樹和渲染樹。

DOM樹表示頁面結(jié)構(gòu),渲染樹表示DOM節(jié)點(diǎn)如何顯示。DOM樹中的每一個需要顯示的節(jié)點(diǎn)在渲染樹種至少存在一個對應(yīng)的節(jié)點(diǎn)(隱藏的DOM元素disply值為none 在渲染樹中沒有對應(yīng)的節(jié)點(diǎn))。渲染樹中的節(jié)點(diǎn)被稱為“幀”或“盒”,符合CSS模型的定義,理解頁面元素為一個具有填充,邊距,邊框和位置的盒子。一旦DOM和渲染樹構(gòu)建完成,瀏覽器就開始顯示(繪制)頁面元素。

當(dāng)DOM的變化影響了元素的幾何屬性(寬或高),瀏覽器需要重新計算元素的幾何屬性,同樣其他元素的幾何屬性和位置也會因此受到影響。瀏覽器會使渲染樹中受到影響的部分失效,并重新構(gòu)造渲染樹。這個過程稱為重排。完成重排后,瀏覽器會重新繪制受影響的部分到屏幕,該過程稱為重繪。由于瀏覽器的流布局,對渲染樹的計算通常只需要遍歷一次就可以完成。但table及其內(nèi)部元素除外,它可能需要多次計算才能確定好其在渲染樹中節(jié)點(diǎn)的屬性,通常要花3倍于同等元素的時間。這也是為什么我們要避免使用table做布局的一個原因。

并不是所有的DOM變化都會影響幾何屬性,比如改變一個元素的背景色并不會影響元素的寬和高,這種情況下只會發(fā)生重繪。

不管頁面發(fā)生了重繪還是重排,它們都會影響性能

二.怎樣觸發(fā)重排

頁面布局和元素幾何屬性的改變就會導(dǎo)致重排 下列情況會發(fā)生重排

  • 頁面初始渲染
  • 添加/刪除可見DOM元素
  • 改變元素位置
  • 改變元素尺寸(寬、高、內(nèi)外邊距、邊框等)
  • 改變元素內(nèi)容(文本或圖片等)
  • 改變窗口尺寸

不同的條件下發(fā)生重排的范圍及程度會不同

某些情況甚至?xí)嘏耪麄€頁面,比如滑動滾動條

三.瀏覽器優(yōu)化

例如:

假如我要用js修改某個div的樣式

div.style.left = '10px'; div.style.top = '10px'; div.style.width = '10px'; div.style.height = '10px';

我們修改了元素的left、top、width、height屬性 ,滿足我們發(fā)生重排的條件 ,理論上會發(fā)生4次重排 ,但是實(shí)際上只會發(fā)生1次重排 ,因?yàn)槲覀儸F(xiàn)代的瀏覽器都有渲染隊(duì)列的機(jī)制 ,當(dāng)我改變了元素的一個樣式會導(dǎo)致瀏覽器發(fā)生重排或重繪時 ,它會進(jìn)入一個渲染隊(duì)列 ,然后瀏覽器繼續(xù)往下看,如果下面還有樣式修改 ,那么同樣入隊(duì) ,直到下面沒有樣式修改 ,瀏覽器會按照渲染隊(duì)列批量執(zhí)行來優(yōu)化重排過程,一并修改樣式 ,這樣就把本該4次的重排優(yōu)化為1次

But,當(dāng)我們寫如下代碼時:

div.style.left = '10px'; console.log(div.offsetLeft);div.style.top = '10px'; console.log(div.offsetTop);div.style.width = '20px'; console.log(div.offsetWidth);div.style.height = '20px'; console.log(div.offsetHeight);

還是1次重排嗎?

Obviously not! 此時發(fā)生了4次重排!

上文不是說瀏覽器有渲染隊(duì)列優(yōu)化機(jī)制嗎? 為什么會有4次?

這和offsetLeft/Top/Width/Height有關(guān)

offsetTop、offsetLeft、offsetWidth、offsetHeight clientTop、clientLeft、clientWidth、clientHeight scrollTop、scrollLeft、scrollWidth、scrollHeight getComputedStyle()(IE中currentStyle)

這些會強(qiáng)制刷新隊(duì)列要求樣式修改任務(wù)立刻執(zhí)行

因?yàn)闉g覽器并不確定在下面的代碼中是否還有修改同樣的樣式,為了獲取到當(dāng)前正確的的即時值不得不立刻執(zhí)行渲染隊(duì)列觸發(fā)重排!!!

四.重繪與重排性能優(yōu)化

1.分離讀寫操作

我們就可以對上面的代碼進(jìn)行優(yōu)化

div.style.left = '10px'; div.style.top = '10px'; div.style.width = '20px'; div.style.height = '20px';console.log(div.offsetLeft); console.log(div.offsetTop); console.log(div.offsetWidth); console.log(div.offsetHeight);

這樣就僅僅發(fā)生1次重排了!

2.樣式集中改變

還是我們最初修改樣式的代碼

div.style.left = '10px'; div.style.top = '10px'; div.style.width = '20px'; div.style.height = '20px';

雖然現(xiàn)代瀏覽器有渲染隊(duì)列的優(yōu)化機(jī)制,但是古董瀏覽器效率仍然底下,觸發(fā)了4次重排 ,即便這樣,我們?nèi)匀豢梢宰龀鰞?yōu)化 ,我們需要cssText屬性合并所有樣式改變

div.style.cssText = 'left:10px;top:10px;width:20px;height:20px;';

這樣只需要修改DOM一次一并處理,僅僅觸發(fā)了1次重排 ,而且只用了一行代碼

除了cssText以外,我們還可以通過修改class類名來進(jìn)行樣式修改

div.className = 'new-class';

這種辦法可維護(hù)性好,還可以幫助我們免除顯示性代碼,但是會消耗一點(diǎn)點(diǎn)的性能

3.緩存布局信息

div.style.left = div.offsetLeft + 1 + 'px'; div.style.top = div.offsetTop + 1 + 'px';

這種讀操作完就執(zhí)行寫操作造成了2次重排

緩存可以進(jìn)行優(yōu)化

var curLeft = div.offsetLeft; var curTop = div.offsetTop; div.style.left = curLeft + 1 + 'px'; div.style.top = curTop + 1 + 'px';

相當(dāng)于是分離讀寫操作,優(yōu)化為1次重排

4.元素批量操作

現(xiàn)在我們想要向ul中循環(huán)添加大量li (如果ul還不存在,最好的辦法是先循環(huán)添加li到ul,然后再把ul添加到文檔,1次重排)

var ul = document.getElementById('demo'); for(var i = 0; i < 1e5; i++){var li = document.createElement('li');var text = document.createTextNode(i);li.appendChild(text);ul.appendChild(li); }

我可以做出下面的優(yōu)化

var ul = document.getElementById('demo'); ul.style.display = 'none'; for(var i = 0; i < 1e5; i++){var li = document.createElement('li');var text = document.createTextNode(i);li.appendChild(text);ul.appendChild(li); } ul.style.display = 'block'; var ul = document.getElementById('demo'); var frg = document.createDocumentFragment(); for(var i = 0; i < 1e5; i++){var li = document.createElement('li');var text = document.createTextNode(i);li.appendChild(text);frg.appendChild(li); }ul.appendChild(frg); var ul = document.getElementById('demo'); var clone = ul.cloneNode(true); for(var i = 0; i < 1e5; i++){var li = document.createElement('li');var text = document.createTextNode(i);li.appendChild(text);clone.appendChild(li); } ul.parentNode.replaceChild(clone,ul);

上面的方法減少重繪和重排的原理很簡單

  • 元素脫離文檔
  • 改變樣式
  • 元素回歸文檔

而改變元素就分別使用了隱藏元素、文檔碎片和克隆元素

總結(jié)

以上是生活随笔為你收集整理的asp.net ajax 怎么获取前端ul li_字节前端提前批面试题:触发了几次回流几次重绘...的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。