AVt天堂网 手机版,亚洲va久久久噜噜噜久久4399,天天综合亚洲色在线精品,亚洲一级Av无码毛片久久精品

當前位置:首頁 > 科技  > 軟件

精準解析 useLayoutEffect 與 useEffect 的執行時機

來源: 責編: 時間:2024-01-17 10:13:53 231觀看
導讀我們前面花了大量篇幅,從基礎、理論、實踐、總結幾個方面,全方位的為大家分析了 useEffect。除此之外,React 還提供了一個與 useEffect 幾乎一樣的 hook,它就是useLayoutEffect。我們約定,useEffect 傳入的第一個參數為 ef

Gj628資訊網——每日最新資訊28at.com

我們前面花了大量篇幅,從基礎、理論、實踐、總結幾個方面,全方位的為大家分析了 useEffect。除此之外,React 還提供了一個與 useEffect 幾乎一樣的 hook,它就是useLayoutEffect。Gj628資訊網——每日最新資訊28at.com

我們約定,useEffect 傳入的第一個參數為 effect,useLayoutEffect 傳入的第一個參數為 layoutEffect。Gj628資訊網——每日最新資訊28at.com

他們的語法為:Gj628資訊網——每日最新資訊28at.com

// 中括號表示參數可選useEffect(effect[, deps])
useLayoutEffect(layoutEffect[, deps])

兩個 hook 有高度相似的語義。Gj628資訊網——每日最新資訊28at.com

第一個參數 layoutEffect 為一個函數,定義為副作用執行邏輯,我們也可以在 layoutEffect 中定義返回函數。當依賴項發生了變化時,返回函數會使用依賴項舊值首先執行,然后再執行 layoutEffect。Gj628資訊網——每日最新資訊28at.com

useLayoutEffect(() => {  // ...    return () => {}}, [state])

第二個參數為依賴項數組。React 內部會使用 Object.is 去比較依賴項是否發生了變化,我們通常會選擇使用 state 或者 props 等響應性數據作為依賴項。依賴項也可以不傳,此時 layoutEffect 在每次狀態發生變化時都會執行。Gj628資訊網——每日最新資訊28at.com

useLayoutEffect 與 useEffect 唯一的區別在于 effect 與 layoutEffect 執行時機的不同。Gj628資訊網——每日最新資訊28at.com

我們借助一個例子來仔細分析他們的準確執行時機。Gj628資訊網——每日最新資訊28at.com

首先是 useEffect。Gj628資訊網——每日最新資訊28at.com

const [count, setCount] = useState(0)useEffect(() => {  document.title = `React ${count}`})

effect 會在組件渲染完成之后執行。這里組件渲染完成的意思是當組件內容已經呈現在頁面上之后,effect 再執行,具體的步驟如下圖所示:Gj628資訊網——每日最新資訊28at.com

Gj628資訊網——每日最新資訊28at.com

在事件循環中, effect 是被定義為宏任務,在下一輪循環執行。Gj628資訊網——每日最新資訊28at.com

然后是 useLayoutEffect。Gj628資訊網——每日最新資訊28at.com

const [count, setCount] = useState(0)useLayoutEffect(() => {  document.title = `React ${count}`})

layoutEffect 會在組件渲染之前執行。具體的步驟如下圖。Gj628資訊網——每日最新資訊28at.com

Gj628資訊網——每日最新資訊28at.com

但是這里如果只是這樣理解的話,估計很多人并不太清晰具體是怎么回事。因為這樣的表達并沒有說清楚具體的執行時刻。更準確的說法是在 commit 之后,組件內容繪制呈現到屏幕之前。Gj628資訊網——每日最新資訊28at.com

例如我們有這樣一段代碼。Gj628資訊網——每日最新資訊28at.com

// 此時已經對DOM發送改變的指令div.style.color = 'red'layoutEffect()

layoutEffect 緊隨 DOM 修改指令發出之后執行,此時雖然 DOM 指令已經發出,但是在瀏覽器的機制中,內容繪制是一個異步的過程,這會兒繪制并沒有執行。Gj628資訊網——每日最新資訊28at.com

因此在事件循環中,layoutEfect 被定義為類似于 Promise 的微任務,在 DOM 指令修改之后,內容繪制之前執行。Gj628資訊網——每日最新資訊28at.com

后續影響

大家可以猜想一下,如果我們在 layoutEffect 中直接去修改 state,會發生什么事情。Gj628資訊網——每日最新資訊28at.com

看看下面這個例子:Gj628資訊網——每日最新資訊28at.com

function Demo() {  const [count, setCount] = useState(0)    useLayoutEffect(() => {    if (count == 0) {      setCount(1)    }  }, [count])      return (    <div>      <div>{count}</div>      <button         onClick={() => setCount(0)}      >        reset 0      </button>    </div>  )}

我們在 state 中聲明一個變量 count,初始值設置為 0,并定義 layoutEffect,其中的邏輯就是當 count == 0 時,將 count 設置為 1。Gj628資訊網——每日最新資訊28at.com

添加一個按鈕,當按鈕點擊時,把 count 重新設置為 0。Gj628資訊網——每日最新資訊28at.com

大家思考一下,此時,頁面上的顯示結果,會在 0 和 1 之間來回切換嗎?Gj628資訊網——每日最新資訊28at.com

答案是不會。Gj628資訊網——每日最新資訊28at.com

因為當我們執行 layoutEffect 時,UI 并沒有進入事件循環的繪制流程,此時還處于 JS 邏輯的執行過程中,那么這個時候執行 setCount,整個邏輯會重新執行,對于瀏覽器而言,JS 針對同一個 UI 發出了兩條不同的指令,在瀏覽器的渲染機制中,也會發生收集行為,將這兩條指令進行合并,最后只執行一條。Gj628資訊網——每日最新資訊28at.com

// setCount(0)div.innerHTML = 0// setCount(1)div.innerHTML = 1

如上例,當 setCount(0) 與 setCount(1)  執行完之后,實際上是發出了兩條修改元素內容的指令給到瀏覽器。Gj628資訊網——每日最新資訊28at.com

當我們使用 useLayoutEffect 時他可能會覆蓋你想要執行的渲染內容,也有可能會阻塞你的正常渲染過程,因此我們在使用它時,需要精確把控他的執行時機,防止出現你不想看到的結果。Gj628資訊網——每日最新資訊28at.com

但是很明顯我們可以看到 layoutEffect 的執行時機比 effect 更早。因此我們也可以在 layoutEffect 中,執行一些輕量的,不直接影響 state 的邏輯。Gj628資訊網——每日最新資訊28at.com

本文鏈接:http://www.tebozhan.com/showinfo-26-63227-0.html精準解析 useLayoutEffect 與 useEffect 的執行時機

聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com

上一篇: Java高頻面試題:過濾器和攔截器兩位難兄難弟區別

下一篇: 這篇文章徹底讓你了解Java與RPA

標簽:
  • 熱門焦點
Top