React

关注公众号 jb51net

关闭
首页 > 网络编程 > JavaScript > javascript类库 > React > React.memo实现

React.memo 实现原理解析

作者:维维酱

React.memo通过props浅比较或自定义函数,结合Fiber优化机制,跳过组件渲染及副作用,下面就来详细的介绍一下,感兴趣的可以了解一下

核心实现概念

React.memo 的本质是一个高阶组件(HOC),它通过比较前后 props 来决定是否跳过组件的重新渲染。

1. 基本结构

在 React 源码中,React.memo 的实现大致如下:

function memo(type, compare) {
  // 创建一个特殊的元素类型
  const elementType = {
    $$typeof: REACT_MEMO_TYPE, // 特殊标识符,表示这是一个 memo 组件
    type, // 被包裹的原始组件
    compare: compare === undefined ? null : compare, // 自定义比较函数
  };
  
  return elementType;
}

2. 在协调(Reconciliation)过程中的处理

当 React 遇到 REACT_MEMO_TYPE 类型的元素时,会执行特殊处理:

// 简化版的协调逻辑
function updateMemoComponent(
  currentFiber, // 当前 Fiber 节点
  workInProgressFiber, // 工作中的 Fiber 节点
  Component, // 被 memo 包裹的组件
  nextProps, // 新的 props
  renderLanes // 渲染优先级
) {
  // 获取之前的 props
  const current = currentFiber.memoizedProps;
  
  // 决定使用哪种比较函数
  let compare = Component.compare;
  if (compare === null) {
    // 默认使用浅比较
    compare = shallowCompare;
  }
  
  // 检查 props 是否相等
  if (compare(current, nextProps)) {
    // Props 没有变化,完全跳过渲染
    // 复用之前的子节点
    return bailoutOnAlreadyFinishedWork(
      currentFiber,
      workInProgressFiber,
      renderLanes
    );
  }
  
  // Props 发生了变化,继续正常渲染流程
  return updateFunctionComponent(
    currentFiber,
    workInProgressFiber,
    Component,
    nextProps,
    renderLanes
  );
}

深入实现细节

1. 浅比较 (shallowCompare) 的实现

React 使用的默认浅比较函数类似于:

function shallowCompare(prevProps, nextProps) {
  // 如果 props 对象引用相同,直接返回 true
  if (prevProps === nextProps) {
    return true;
  }
  
  // 检查 props 键的数量
  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 进行严格比较(类似于 ===,但处理了 NaN 和 +0/-0 的情况)
    if (!Object.is(prevProps[key], nextProps[key])) {
      return false;
    }
  }
  
  return true;
}

2. Fiber 架构中的优化机制

在 React 的 Fiber 架构中,React.memo 的优化是通过以下机制实现的:

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
    );
  }
  
  // 处理其他类型的组件...
}

性能考虑与实现优化

1. 记忆化策略

React.memo 的实现采用了记忆化(Memoization)策略:

2. 选择性优化

React 不会对所有组件都应用 memo 优化,因为:

3. 与其他优化机制的协同

React.memo 与 React 的其他优化机制协同工作:

实际应用中的实现考虑

1. 自定义比较函数的高级用法

// 深度比较实现(不推荐在生产环境使用,仅作示例)
function deepCompare(prevProps, nextProps) {
  return JSON.stringify(prevProps) === JSON.stringify(nextProps);
}

// 选择性比较
function selectiveCompare(prevProps, nextProps) {
  // 只比较我们关心的属性
  return prevProps.importantValue === nextProps.importantValue;
}

const ExpensiveComponent = React.memo(
  function ExpensiveComponent(props) {
    // 组件实现
  },
  selectiveCompare // 使用自定义比较函数
);

2. 与 Hooks 的交互

React.memo 的实现需要考虑与 Hooks 的交互:

function MyComponent(props) {
  // 即使使用 React.memo,内部状态变化仍会导致重新渲染
  const [state, setState] = useState(0);
  
  // 使用 useMemo 和 useCallback 可以进一步优化
  const computedValue = useMemo(() => {
    return expensiveCalculation(props.someValue);
  }, [props.someValue]);
  
  const handleClick = useCallback(() => {
    // 处理点击
  }, []);
  
  return <div>{/* ... */}</div>;
}

export default React.memo(MyComponent);

总结

React.memo 的实现原理可以概括为:

  1. 高阶组件包装:通过创建特殊类型的 React 元素标记 memo 组件
  2. 协调阶段拦截:在协调过程中识别 memo 组件并执行特殊处理
  3. Props 比较:使用浅比较或自定义比较函数判断 props 是否变化
  4. 渲染优化:如果 props 未变化,跳过组件的渲染和子树的协调过程
  5. 结果复用:直接复用之前的渲染结果,避免不必要的计算和 DOM 操作

这种实现方式体现了 React 性能优化的核心思想:用较小的比较成本换取可能很大的渲染成本节约

到此这篇关于React.memo 实现原理解析的文章就介绍到这了,更多相关React.memo实现内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文