亚洲视频二区_亚洲欧洲日本天天堂在线观看_日韩一区二区在线观看_中文字幕不卡一区

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.430618.com 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

title: JS中操作DOM是"同步"還是"異步"? date: 2019-08-08 17:55:00 tags:

  • JAVAScript categories: JavaScript

很多時候"不得已"使用js操作DOM,這個操作過程到底是"同步"的還是"異步"呢?

很多時候"不得已"使用js操作DOM,這個操作過程到底是"同步"的還是"異步"呢?

一、操作DOM的栗子

按理說,在js的執行中,對于DOM的操作都是同步執行的,

<body></body>
<script>
 var body = document.querySelector('body');
 console.log(`1`);
 var cDiv = document.createElement('div');
 console.log(cDiv)
 console.log(`2`);
 body.AppendChild(cDiv)
 console.log(body);
</script>

以上結果目前和我們預想的結果是一致的,自上而下依次同步執行,這里劃重點,js引擎線程。

接下來做一點修改

<style>

.easy {

width: 200px;

height: 200px;

background: lightgoldenrodyellow;

}

.hard {

background: lightsalmon;

transition: 2s all;

}

</style>

<body></body>

<script>

var body = document.querySelector('body');

console.log(`1`);

var cDiv = document.createElement('div');

console.log(cDiv);

console.log(`2`);

body.appendChild(cDiv)

console.log(body);

cDiv.classList.add('easy')

console.log(`3`);

// ======================

for(var i = 0;i<3000000000;i++);

cDiv.classList.add('hard')

console.log(cDiv)

// ======================

</script>

既然是同步執行,那我在添加第二個樣式hard之前阻塞一下,理論上在阻塞的情況下<div>應該的背景色是淡黃色吧?不過跑一下完全不對勁啊,出來的很慢不說,竟然直接就橘色了。這里劃重點,GUI渲染線程

二、捋一捋問題

  1. 有阻塞,在阻塞時沒有顯示已有樣式,究竟是不是同步執行的?
  2. console.log()的內容并不是空,只是返回的很慢,看著像異步執行?
  3. 過度樣式被忽略了,但背景色覆蓋執行了,是什么原因?

三、依次解題

  1. js執行順序不在這里細說,常見能夠改變執行隊列的Promise、setTimeout、<script>標簽等等都沒有在這里出現,所以確認是同步執行無疑。
  2. 既然同步執行為什么會有"異步"的效果,這里要說到上文劃重點內容: js引擎線程與GUI渲染線程。也就是說,js引擎線程與GUI渲染線程互斥,這是線程之間的"同步"造成的操作DOM時的"異步"效果。
  3. <div>的樣式為什么沒有生效呢?明明有一個過渡效果。原因是:瀏覽器的渲染時會執行優化策略,即將多個同一DOM下的樣式合并后渲染。

四、 總結

  1. js引擎線程與GUI渲染線程線程間的互斥,引起了對js操作DOM的"異步"問題。
  2. GUI渲染線程在能夠執行的情況下的優化策略,渲染出的是最終得到的樣式結果。

具體的渲染線程的內容,不在這次討論范圍之內嘛。

雖然原因找到了,不過問題好像還在。

五、 解決問題

如果產品一定要從js創建出來的div擁有炫酷的特效(比如上面的過度樣式)。 呵呵呵呵

直接整理一下來自知乎各方大佬的解題思路, 這里不僅僅是過度樣式,類似問題依然有效。

分析問題:

  1. 過度效果是至少由A變B,也就是至少存有兩個不同狀態;
  2. 由于上文所講的GUI渲染線程與js引擎的互斥會造成一種"同步"執行的效果,所以創建<div>本身已經被滯后了,缺少A。
  3. 又由于GUI渲染線程優化策略,最后結果B將覆蓋可以覆蓋的所有。缺少了A(被覆蓋),之后被渲染出現在document內。
  4. 本身已經是B,且沒有A狀態,過度效果無效。

解決方向就是使<div>擁有一個初始狀態A就搞定了。(提前將生成的DOM渲染到document上)


解決方法一:

	cDiv.classList.add('easy')
	// for(var i = 0;i<3000000000;i++);
	setTimeout(() => {
		cDiv.classList.add('hard')
	}, 0)

思路: 利用setTimeout方法,改變執行隊列。也就是手動將js引擎滯后,使js引擎結束,被掛起的GUI渲染線程執行,擁有了初始狀態A后,在執行過度效果就OK了。

解決方法二(推薦):

	cDiv.classList.add('easy')
	cDiv.clientLeft; // 任一觸發頁面回流的方法皆可
	cDiv.classList.add('hard')

思路:既然可以讓js引擎滯后,那也可以讓GUI渲染線程提前,用立即觸發回流的任意方法,使之前在渲染隊列中的狀態A生效。 相對優點在于,同樣是觸發回流,方法二從代碼可讀性或操作性上都略勝一籌,優秀團隊有這種追求也是自然而然的。

分享到:
標簽:DOM
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定