日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
聊聊React中的隱藏彩蛋功能

大家好,我卡頌。

創(chuàng)新互聯(lián)建站是一家專業(yè)從事成都網(wǎng)站建設(shè)、成都網(wǎng)站設(shè)計的網(wǎng)絡(luò)公司。作為專業(yè)網(wǎng)站建設(shè)公司,創(chuàng)新互聯(lián)建站依托的技術(shù)實力、以及多年的網(wǎng)站運營經(jīng)驗,為您提供專業(yè)的成都網(wǎng)站建設(shè)、全網(wǎng)營銷推廣及網(wǎng)站設(shè)計開發(fā)服務(wù)!

React的代碼量可以說是相當(dāng)龐大。在如此龐大的庫中是否存在「文檔中未提及,但是實際存在的功能」呢?

答案是肯定的。

本文將向你介紹3個文檔中未提及的隱藏彩蛋功能。

ref cleanup

在當(dāng)前React中,Ref存在兩種數(shù)據(jù)結(jié)構(gòu):

  1. (instance: T) => void
  2. {current: T}

對于大部分需求,我們會使用第二種數(shù)據(jù)結(jié)構(gòu)。同時,他也是useRef、createRef返回的數(shù)據(jù)結(jié)構(gòu)。

第一種數(shù)據(jù)結(jié)構(gòu)主要用于DOM監(jiān)控,比如在下面的例子中,div的尺寸會反映到height狀態(tài)中:

function MeasureExample() {
  const [height, setHeight] = useState(0);

  const measuredRef = useCallback(node => {
    if (node !== null) {
      setHeight(node.getBoundingClientRect().height);
    }
  }, []);

  return (
    
Hello 卡頌
); }

但在上面的例子中,DOM的尺寸變化無法實時反映到height狀態(tài)。為了反映實時變化,需要使用監(jiān)控DOM的原生API,比如:

  • ResizeObserver[1],監(jiān)控DOM尺寸變化。
  • IntersectionObserver[2],監(jiān)控DOM可視區(qū)域變化。
  • MutationObserver[3],監(jiān)控DOM樹變化。

這些API通常是事件驅(qū)動,這就涉及到「當(dāng)不需要監(jiān)控后,解綁事件」。

既然事件綁定是在ref回調(diào)中進行的,很自然的,解綁事件也應(yīng)該在ref回調(diào)中進行。比如,用ResizeObserver改造上述例子:

function MeasureExample() {
  const [entry, setEntry] = useState();
  
  const measuredRef = useCallback((node) => {
    const observer = new ResizeObserver(([entry]) => {
      setEntry(entry)
    })

    observer.observe(node)
    // 解綁事件
    return () => {
      observer.disconnect()
    }
  }, [])

  return (
    
Hello 卡頌
); }

在這個場景中,我們希望函數(shù)類型的ref可以返回一個新函數(shù),用于解綁事件(類似useEffect回調(diào)的返回值)。

實際上,在19年的#issues 15176[4]中就有人提出這個問題。在去年底的#pull 25686[5]中相關(guān)改動已經(jīng)合并到React main分支。

當(dāng)前React文檔中Ref的部分還未提及這個功能改動??赡茉谖磥淼哪硞€小版本中,會上線這個功能。

Module Component

你覺得下面的函數(shù)組件能渲染出「hello」么:

function Child() {
  return {
    render() {
      return "hello";
    }
  };
}

答案是 —— 可以,見Module Component在線示例[6]。

其實這是一種上古時期就存在的組件形式,叫做Module Component(即函數(shù)組件返回帶有render屬性的對象)。

當(dāng)遇到Module Component,React會將對應(yīng)函數(shù)組件(上例中的Child組件)轉(zhuǎn)換為Class Component,后續(xù)更新流程與Class Component無異。

Module Component預(yù)計會在未來的某個版本被移除(見#pull 15145[7]),所以文檔中并未提及。

要說有啥實際作用,沒準可以給你同事帶來點小小困惑......

開啟全局并發(fā)更新

在v18中,只有使用并發(fā)特性(比如useTransiton)觸發(fā)的更新才是并發(fā)更新,其他情況觸發(fā)的更新都是同步更新。

如何才能不使用并發(fā)特性,又能全局開啟并發(fā)更新呢?答案是在項目中加入下面這行咒語:

React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentBatchConfig.transition = {
  帥哥: '卡頌'
};

比如,對于如下例子,渲染一個耗時的列表(每個Item組件render會耗時5ms):

function App() {
  return (
    
    {Array.from({ length: 100 }).map((_, i) => ( {i} ))}
); } function Item({ children }) { const cur = performance.now(); while (performance.now() - cur < 5) {} return
  • {children}
  • ; }

    并發(fā)示例地址[8]。

    不加上咒語時的渲染火炬圖如下,整個更新流程在一個宏任務(wù)中,耗時513ms:

    加上咒語時的渲染火炬圖如下,整個更新流程被時間切片,每個切片5ms左右:

    咒語為什么會起作用呢?

    在React、ReactDOM中都存在變量__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED,這個變量的作用是 —— 在不同包之間共享數(shù)據(jù)。

    比如,所有Hook都是從React包中導(dǎo)出的,但Hook的具體實現(xiàn)在ReactDOM包中。為了在他們之間共享Hook,就需要一個媒介,這就是__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED。

    類似的,「更新」相關(guān)數(shù)據(jù)也需要在React與ReactDOM間共享,其中就包括 —— 更新是否是并發(fā)更新。

    當(dāng)我們賦值React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentBatchConfig.transition后,React會認為當(dāng)前更新是并發(fā)更新。

    通過這種方式,就能全局開啟并發(fā)更新。

    當(dāng)然,我并不建議你隨意更改__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED下的數(shù)據(jù),畢竟這個變量的名字還是挺唬人的。

    總結(jié)

    以上便是3個React中的隱藏彩蛋功能。其實除了他們之外,React中還有很多沒有暴露出來的API,比如類似Vue中Keep-Alive的Offscreen Component。

    當(dāng)前要想體驗Offscreen Component只能通過Suspense間接體驗(Suspense能夠在pending與掛載組件間切換就是利用Offscreen Component)。

    還有什么你知道的React隱藏功能?

    參考資料

    [1]ResizeObserver:https://developer.mozilla.org/zh-CN/docs/Web/API/ResizeObserver。

    [2]IntersectionObserver:https://developer.mozilla.org/zh-CN/docs/Web/API/IntersectionObserver。

    [3]MutationObserver:https://developer.mozilla.org/zh-CN/docs/Web/API/MutationObserver。

    [4]#issues 15176:https://github.com/facebook/react/issues/15176。

    [5]#pull 25686:https://github.com/facebook/react/pull/25686。

    [6]Module Component在線示例:https://codesandbox.io/s/boring-proskuriakova-u4pzyl?file=/src/App.js。

    [7]#pull 15145:https://github.com/facebook/react/pull/15145。

    [8]并發(fā)示例地址:https://codesandbox.io/s/zen-ben-nldijx?file=/src/index.js。


    網(wǎng)頁標(biāo)題:聊聊React中的隱藏彩蛋功能
    轉(zhuǎn)載源于:http://www.dlmjj.cn/article/djhphcc.html