Virtual DOM与React性能疑问及父组件更新时子组件重渲染问题
1. Virtual DOM 和 React 性能的那些事儿
很多刚接触React的同学都会有个疑惑:Virtual DOM 不就是在真实DOM上面多套了一层吗?这不是平白增加开销?其实这是对它的误解。
React用Virtual DOM的核心目的,是减少真实DOM的操作次数。咱们都知道,真实DOM的修改代价极高——每次改DOM都会触发浏览器的重排和重绘,这俩操作非常耗性能。而Virtual DOM是用普通JS对象模拟的DOM结构,React会先对比新旧两个Virtual DOM的差异(这个过程叫diffing),精准找出需要更新的最小部分,只对真实DOM做必要的修改,而不是把整个DOM树全换掉。
举个实际的例子:如果要更新一个100条数据的列表里的某一项,直接操作真实DOM可能得重新渲染整个列表,但Virtual DOM能定位到那唯一变化的项,只更新对应的DOM节点,这就把性能开销降到了最低。
不过得说清楚:Virtual DOM不是在所有场景下都比手动操作DOM快——比如你只是改个简单的按钮文字,直接用document.getElementById可能比React更快。但对于复杂的UI应用,Virtual DOM带来的可预测性、批量更新能力,是手动操作DOM根本没法比的,这也是React能高效管理复杂状态的关键。
2. 父组件更新时,所有子组件都会跟着重渲染吗?
答案是:默认情况下会,但我们有一堆办法避免这种不必要的重渲染。
React的默认逻辑是:当父组件的state或props更新时,会重新渲染父组件,同时递归地重渲染它所有的子组件——哪怕子组件的props和state完全没变化。这是因为React默认不知道子组件是否需要更新,所以会走一遍完整的渲染流程。
但这种默认行为在复杂应用里会造成性能浪费,所以React给我们提供了几个优化工具:
React.memo:用来包裹函数组件,它会对比组件的新旧props,如果props没变化,就直接跳过重渲染,相当于类组件里的PureComponent。const Child = React.memo(({ name }) => { console.log('Child 渲染了'); return <div>{name}</div>; });- 类组件的
shouldComponentUpdate:手动写判断逻辑,返回false就会跳过当前组件的重渲染。 useMemo和useCallback:当你给子组件传递函数、数组或对象这类引用类型的props时,这俩Hook能缓存这些值,避免父组件每次渲染都生成新的引用,导致子组件误以为props变了而触发重渲染。
比如你给子组件传了一个点击事件函数,父组件每次渲染都会创建新的函数实例,哪怕逻辑没变,子组件也会重渲染。用useCallback缓存这个函数就能解决:
const Parent = () => { const handleClick = useCallback(() => { console.log('点击了'); }, []); // 依赖数组为空,只会创建一次函数实例 return <Child onClick={handleClick} />; };
内容的提问来源于stack exchange,提问作者saransh mehra

