欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 汽车 > 时评 > 从 Vue 到 React:React.memo + useCallback 组合技

从 Vue 到 React:React.memo + useCallback 组合技

2025/4/25 13:19:29 来源:https://blog.csdn.net/Curry_On/article/details/147458268  浏览:    关键词:从 Vue 到 React:React.memo + useCallback 组合技

目录

    • 一、Vue 与 React 的组件更新机制对比
    • 二、React.memo 是什么?
    • 三、常见坑:为什么我用了 React.memo 还是会重新渲染?
    • 四、解决方案:useMemo / useCallback 缓存引用
    • 五、Vue 3 中有类似的性能控制需求吗?
    • 六、组合优化小技巧总结
    • 七、不过话又说回来

一、Vue 与 React 的组件更新机制对比

在 Vue 中,组件的更新依赖于响应式系统的依赖追踪:

<!-- Vue 模板中 -->
<Child :data="data" />
  • 父组件更新时,Vue 会判断 data 是否变更;
  • data 是响应式对象,它会做“依赖追踪”;
  • 子组件是否更新由内部响应式系统决定,开发者很少手动优化。

而在 React 中:

<Child data={data} />
  • React 默认只做浅比较
  • 只要 data 是一个新对象(哪怕值完全相同),就会触发 Child 重新渲染;
  • 所以你需要用 React.memo + useCallback + useMemo手动优化性能。

二、React.memo 是什么?

const MemoizedComponent = React.memo(Component);

React.memo 是一个高阶组件,用于缓存函数组件的渲染结果,仅在 props 变化时才重新渲染。

它做了啥?

  • 对 props 进行浅比较
  • 如果 props 没变(===),则跳过子组件渲染;

三、常见坑:为什么我用了 React.memo 还是会重新渲染?

来看一个经典例子:

const Parent = () => {const [count, setCount] = useState(0);const data = { text: "hello" }; // ⚠️ 每次渲染都是新对象!return (<><button onClick={() => setCount(c => c + 1)}>+</button><Child data={data} /></>);
};const Child = React.memo(({ data }) => {console.log("Child render");return <div>{data.text}</div>;
});

🔎 结果:

  • 每点一次按钮,Child 都会重新渲染!
  • 虽然 data 的值没有变,但对象引用变了{} 是新对象);
  • 所以 React.memo 判定 props 变了,触发更新。

四、解决方案:useMemo / useCallback 缓存引用

const data = useMemo(() => ({ text: "hello" }), []);

或者对于函数:

const handleClick = useCallback(() => {console.log("clicked");
}, []);

这就保证了 引用不变,从而让 React.memo 的比较机制生效。


完整示例:

const Parent = () => {const [count, setCount] = useState(0);const data = useMemo(() => ({ text: "hello" }), []);const handleClick = useCallback(() => {console.log("clicked");}, []);return (<><button onClick={() => setCount(c => c + 1)}>+</button><Child data={data} onClick={handleClick} /></>);
};const Child = React.memo(({ data, onClick }) => {console.log("Child render");return <button onClick={onClick}>{data.text}</button>;
});

🧠 现在:

  • 点击按钮不会触发 Child 重新渲染;
  • 因为 dataonClick 的引用没变;
  • React.memo 正常工作,组件性能得到提升。

五、Vue 3 中有类似的性能控制需求吗?

Vue 3 的响应式机制天然做了很多“追踪 + 缓存”,组件不会因为 props 引用变化而轻易重新渲染,只要你不写复杂嵌套 watch / watchEffect,基本不用显式控制更新。

但 React 是“纯函数组件 + 浅比较 + 显式控制”模式,性能优化基本靠开发者手动干预。


六、组合优化小技巧总结

目标工具组合
避免组件重复渲染React.memo
保证函数 prop 引用稳定useCallback
保证对象 prop 引用稳定useMemo
高性能组件拆分 + 精准更新控制React.memo + useCallback + useMemo

七、不过话又说回来

关于这个优化的组合手段,在实际开发中,往往不是“用不用”,而是“什么时候用、用在哪、用多少”。盲目无脑使用很容易陷入“性能优化反而拖慢开发效率”的误区。

❌ 常见错误:

const value = useMemo(() => expensiveCalculation(data), [data]);

很多人会这么写,但:

  • 如果 expensiveCalculation() 实际上并不耗时;
  • 或者 data 频繁变化,memo 无意义;
  • 那么你加了 useMemo 不但没有优化,还增加了复杂度。

所以重点是:只有在“真的影响性能”时才用。


那【何时该用】呢?

场景是否建议使用 Memo 类 Hook
父组件频繁更新,子组件 props 不变✅ 使用 React.memo + useCallback
传递对象或函数给子组件✅ 保持引用稳定,避免不必要更新
有昂贵计算(排序、大数据处理等)✅ 使用 useMemo 缓存计算结果
props 很简单,子组件渲染开销很小(比如一个 <span>❌ 不需要,优化反而复杂
自己写了一堆 memo,但还是更新很慢❌ 可能是 Context/状态设计问题
拥有大量动态子组件(如大表格、虚拟滚动列表)✅ 搭配 memouseMemo、分块渲染等
使用 Context 时⚠️ memo 可能无效,需额外处理

下面看看两类重点问题

  1. Context 泄漏导致 memo 失效
<MyContext.Provider value={contextValue}><MemoizedChild />
</MyContext.Provider>

每次 context value 变,整个 Provider 下所有组件都会重新渲染,哪怕用了 React.memo

解决方式:

  • 避免 context value 是新对象(useMemo 包装);
  • 或者将 context 拆分成多个 Provider;
  • 或使用第三方库如 zustand 做 context 分片;

  1. 大量嵌套组件的 props 传递链

假如你有一个页面,父组件的数据变化会层层传到第 6 层子组件,那你会发现:

  • 就算第 6 层用 React.memo,如果 props 是对象或函数,还是会触发更新;
  • useMemo / useCallback 会让代码变得繁琐难读。

解决方式:

  • 使用全局状态管理(如 zustand)代替 props;
  • 通过组合组件逻辑 & 提前拆分优化更新粒度;
  • 或者用 memo + useContextSelector(experimental)做局部响应式。

Vue 的响应式机制帮我们自动完成“依赖追踪 + 缓存更新”,你不用担心引用变化;
但在 React 中,这些都需要你自己判断并手动处理。

所以:

  • 不要滥用 memo 系列 Hook,性能优化是“按需用药”;
  • 越复杂的页面越要拆组件,避免“父更新拖着全家跑”;
  • 适度引入状态管理工具,别让 props 变成“传话筒”。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词