欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

React.memo 實(shí)現(xiàn)原理解析

 更新時間:2025年09月09日 11:10:45   作者:維維醬  
React.memo通過props淺比較或自定義函數(shù),結(jié)合Fiber優(yōu)化機(jī)制,跳過組件渲染及副作用,下面就來詳細(xì)的介紹一下,感興趣的可以了解一下

核心實(shí)現(xiàn)概念

React.memo 的本質(zhì)是一個高階組件(HOC),它通過比較前后 props 來決定是否跳過組件的重新渲染。

1. 基本結(jié)構(gòu)

在 React 源碼中,React.memo 的實(shí)現(xiàn)大致如下:

function memo(type, compare) {
  // 創(chuàng)建一個特殊的元素類型
  const elementType = {
    $$typeof: REACT_MEMO_TYPE, // 特殊標(biāo)識符,表示這是一個 memo 組件
    type, // 被包裹的原始組件
    compare: compare === undefined ? null : compare, // 自定義比較函數(shù)
  };
  
  return elementType;
}

2. 在協(xié)調(diào)(Reconciliation)過程中的處理

當(dāng) React 遇到 REACT_MEMO_TYPE 類型的元素時,會執(zhí)行特殊處理:

// 簡化版的協(xié)調(diào)邏輯
function updateMemoComponent(
  currentFiber, // 當(dāng)前 Fiber 節(jié)點(diǎn)
  workInProgressFiber, // 工作中的 Fiber 節(jié)點(diǎn)
  Component, // 被 memo 包裹的組件
  nextProps, // 新的 props
  renderLanes // 渲染優(yōu)先級
) {
  // 獲取之前的 props
  const current = currentFiber.memoizedProps;
  
  // 決定使用哪種比較函數(shù)
  let compare = Component.compare;
  if (compare === null) {
    // 默認(rèn)使用淺比較
    compare = shallowCompare;
  }
  
  // 檢查 props 是否相等
  if (compare(current, nextProps)) {
    // Props 沒有變化,完全跳過渲染
    // 復(fù)用之前的子節(jié)點(diǎn)
    return bailoutOnAlreadyFinishedWork(
      currentFiber,
      workInProgressFiber,
      renderLanes
    );
  }
  
  // Props 發(fā)生了變化,繼續(xù)正常渲染流程
  return updateFunctionComponent(
    currentFiber,
    workInProgressFiber,
    Component,
    nextProps,
    renderLanes
  );
}

深入實(shí)現(xiàn)細(xì)節(jié)

1. 淺比較 (shallowCompare) 的實(shí)現(xiàn)

React 使用的默認(rèn)淺比較函數(shù)類似于:

function shallowCompare(prevProps, nextProps) {
  // 如果 props 對象引用相同,直接返回 true
  if (prevProps === nextProps) {
    return true;
  }
  
  // 檢查 props 鍵的數(shù)量
  const prevKeys = Object.keys(prevProps);
  const nextKeys = Object.keys(nextProps);
  
  if (prevKeys.length !== nextKeys.length) {
    return false;
  }
  
  // 逐個比較每個屬性值
  for (let i = 0; i < prevKeys.length; i++) {
    const key = prevKeys[i];
    
    // 使用 Object.is 進(jìn)行嚴(yán)格比較(類似于 ===,但處理了 NaN 和 +0/-0 的情況)
    if (!Object.is(prevProps[key], nextProps[key])) {
      return false;
    }
  }
  
  return true;
}

2. Fiber 架構(gòu)中的優(yōu)化機(jī)制

在 React 的 Fiber 架構(gòu)中,React.memo 的優(yōu)化是通過以下機(jī)制實(shí)現(xiàn)的:

  • 提前中止渲染:在 beginWork 階段,如果檢測到是 memo 組件且 props 未變化,React 會立即中止當(dāng)前組件的渲染工作。
  • 子樹復(fù)用:通過 bailoutOnAlreadyFinishedWork 函數(shù),React 會標(biāo)記整個子樹為"無需更新",直接復(fù)用之前的渲染結(jié)果。
  • 跳過副作用:由于組件沒有重新渲染,相關(guān)的副作用(如 useEffect)也不會被觸發(fā)。

3. 與 React 渲染流程的整合

// 簡化的渲染流程
function beginWork(currentFiber, workInProgressFiber, renderLanes) {
  // 檢查是否是 memo 組件
  if (workInProgressFiber.type && workInProgressFiber.type.$$typeof === REACT_MEMO_TYPE) {
    return updateMemoComponent(
      currentFiber,
      workInProgressFiber,
      workInProgressFiber.type.type, // 提取原始組件
      workInProgressFiber.pendingProps,
      renderLanes
    );
  }
  
  // 處理其他類型的組件...
}

性能考慮與實(shí)現(xiàn)優(yōu)化

1. 記憶化策略

React.memo 的實(shí)現(xiàn)采用了記憶化(Memoization)策略:

  • 存儲之前的結(jié)果:React 會存儲組件上一次的渲染結(jié)果(在 Fiber 節(jié)點(diǎn)的 memoizedStatememoizedProps 中)
  • 比較成本與渲染成本的權(quán)衡:淺比較的計算成本遠(yuǎn)低于組件的渲染成本(包括虛擬 DOM 創(chuàng)建和差異比較)

2. 選擇性優(yōu)化

React 不會對所有組件都應(yīng)用 memo 優(yōu)化,因?yàn)椋?/p>

  • 比較本身有成本
  • 對于頻繁更新或 props 經(jīng)常變化的組件,memo 可能帶來負(fù)收益

3. 與其他優(yōu)化機(jī)制的協(xié)同

React.memo 與 React 的其他優(yōu)化機(jī)制協(xié)同工作:

  • Context 優(yōu)化:即使使用 React.memo,如果組件消費(fèi)的 Context 值發(fā)生變化,組件仍會重新渲染
  • 狀態(tài)更新優(yōu)化:組件內(nèi)部的狀態(tài)更新不受 React.memo 影響

實(shí)際應(yīng)用中的實(shí)現(xiàn)考慮

1. 自定義比較函數(shù)的高級用法

// 深度比較實(shí)現(xiàn)(不推薦在生產(chǎn)環(huán)境使用,僅作示例)
function deepCompare(prevProps, nextProps) {
  return JSON.stringify(prevProps) === JSON.stringify(nextProps);
}

// 選擇性比較
function selectiveCompare(prevProps, nextProps) {
  // 只比較我們關(guān)心的屬性
  return prevProps.importantValue === nextProps.importantValue;
}

const ExpensiveComponent = React.memo(
  function ExpensiveComponent(props) {
    // 組件實(shí)現(xiàn)
  },
  selectiveCompare // 使用自定義比較函數(shù)
);

2. 與 Hooks 的交互

React.memo 的實(shí)現(xiàn)需要考慮與 Hooks 的交互:

function MyComponent(props) {
  // 即使使用 React.memo,內(nèi)部狀態(tài)變化仍會導(dǎo)致重新渲染
  const [state, setState] = useState(0);
  
  // 使用 useMemo 和 useCallback 可以進(jìn)一步優(yōu)化
  const computedValue = useMemo(() => {
    return expensiveCalculation(props.someValue);
  }, [props.someValue]);
  
  const handleClick = useCallback(() => {
    // 處理點(diǎn)擊
  }, []);
  
  return <div>{/* ... */}</div>;
}

export default React.memo(MyComponent);

總結(jié)

React.memo 的實(shí)現(xiàn)原理可以概括為:

  1. 高階組件包裝:通過創(chuàng)建特殊類型的 React 元素標(biāo)記 memo 組件
  2. 協(xié)調(diào)階段攔截:在協(xié)調(diào)過程中識別 memo 組件并執(zhí)行特殊處理
  3. Props 比較:使用淺比較或自定義比較函數(shù)判斷 props 是否變化
  4. 渲染優(yōu)化:如果 props 未變化,跳過組件的渲染和子樹的協(xié)調(diào)過程
  5. 結(jié)果復(fù)用:直接復(fù)用之前的渲染結(jié)果,避免不必要的計算和 DOM 操作

這種實(shí)現(xiàn)方式體現(xiàn)了 React 性能優(yōu)化的核心思想:用較小的比較成本換取可能很大的渲染成本節(jié)約。

到此這篇關(guān)于React.memo 實(shí)現(xiàn)原理解析的文章就介紹到這了,更多相關(guān)React.memo實(shí)現(xiàn)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 淺析react里面如何封裝一個通用的Ellipsis組件

    淺析react里面如何封裝一個通用的Ellipsis組件

    這篇文章主要為大家詳細(xì)介紹了在react里面如何封裝一個通用的Ellipsis組件,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2024-12-12
  • 詳解react-refetch的使用小例子

    詳解react-refetch的使用小例子

    這篇文章主要介紹了詳解react-refetch的使用小例子,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2019-02-02
  • react16+antd4 RangePicker組件實(shí)現(xiàn)時間禁選示例

    react16+antd4 RangePicker組件實(shí)現(xiàn)時間禁選示例

    這篇文章主要為大家介紹了react16+antd4 RangePicker 時間禁選示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-05-05
  • React前端開發(fā)createElement源碼解讀

    React前端開發(fā)createElement源碼解讀

    這篇文章主要為大家介紹了React前端開發(fā)createElement源碼解讀,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-11-11
  • 詳解React Native 采用Fetch方式發(fā)送跨域POST請求

    詳解React Native 采用Fetch方式發(fā)送跨域POST請求

    這篇文章主要介紹了詳解React Native 采用Fetch方式發(fā)送跨域POST請求,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-11-11
  • 深入理解React 三大核心屬性

    深入理解React 三大核心屬性

    本文主要介紹了React 三大核心屬性,主要包括State屬性,Props屬性,Refs屬性,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • React Native提供自動完成的下拉菜單的方法示例

    React Native提供自動完成的下拉菜單的方法示例

    這篇文章主要為大家介紹了React Native提供自動完成的下拉菜單的方法示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-10-10
  • 使用react實(shí)現(xiàn)手機(jī)號的數(shù)據(jù)同步顯示功能的示例代碼

    使用react實(shí)現(xiàn)手機(jī)號的數(shù)據(jù)同步顯示功能的示例代碼

    本篇文章主要介紹了使用react實(shí)現(xiàn)手機(jī)號的數(shù)據(jù)同步顯示功能的示例代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-04-04
  • React優(yōu)雅的封裝SvgIcon組件示例

    React優(yōu)雅的封裝SvgIcon組件示例

    這篇文章主要為大家介紹了React優(yōu)雅的封裝SvgIcon組件示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-02-02
  • react中如何使用監(jiān)聽

    react中如何使用監(jiān)聽

    在 React 中,您可以使用?addEventListener?函數(shù)來監(jiān)聽事件,本文通過實(shí)例代碼給大家介紹react中如何使用監(jiān)聽,感興趣的朋友跟隨小編一起看看吧
    2023-10-10

最新評論