react如何更新DOM的一部分?

Posted

技术标签:

【中文标题】react如何更新DOM的一部分?【英文标题】:How does react update part of the DOM? 【发布时间】:2019-02-04 21:05:20 【问题描述】:

我知道这个主题显然已经讨论了很多,但我不确定如何研究我的问题相当具体,我希望它遵循这里的规则。

我知道要决定是否更新 DOM,react 会将虚拟 DOM 与重新渲染的 DOM 进行比较。但我只是不明白它是否决定更新它 - 它是更新特定重新渲染组件的所有元素,还是只知道更新组件的更改元素?

提前致谢,

【问题讨论】:

这是一个简单的答案,但它应该回答你的问题。当状态改变时,你的整个应用程序树被重新渲染到虚拟 dom。然后将虚拟 dom 与 LAST 虚拟 dom 进行区分,并更改必要的 DOM 元素。无论涉及到哪些组件来生成 vdom 都无关紧要 【参考方案1】:

reconciliation documentation 是一个更好地了解 react 如何决定重新渲染元素的好地方,但我可以总结一下:

每次调用 render() ,react 都会创建一个新的虚拟 DOM,其中根节点是调用 render 函数的组件。当组件的状态 或其任何子组件的 props 发生变化时,将调用 render() 函数。 render() 函数从根开始销毁所有旧的虚拟 DOM 节点,并创建一个全新的虚拟 DOM。

为了确保组件的重新渲染顺畅高效,React 使用Diffing Algorithm 将创建新树所需的时间减少到 O(n) 的时间复杂度,通常是复制的时间复杂度树 > O(n^2)。它实现这一点的方法是在 DOM 中的每个元素上使用“key”属性。 React 知道,它可以检查 DOM 中每个节点上的“key”属性,而不是从头开始创建每个元素。这就是为什么如果你没有设置每个元素的“key”属性你会得到一个警告,React 使用这些键来极大地提高它的渲染速度。

【讨论】:

作为补充,React 没有明确地使用键作为创建元素和它引用的 DOM 节点之间的一对一。随着 Fiber 的引入,React 使用 Fiber 节点作为描述你想要的元素和你最终得到的 DOM 节点之间的关联。 "render() 函数从根开始销毁所有旧的虚拟 DOM 节点,并创建一个全新的虚拟 DOM。我希望确认这一点,但您能否找到源代码,因为我在您提供的文档链接中没有找到这个确切的信息(重新表述我的理解:如果元素树下的任何子元素是从头开始重新创建整个虚拟 DOM 是重新渲染)。【参考方案2】:

render() 方法的执行并不意味着 react 也渲染了实际的 DOM。 React 保留了虚拟 DOM 的两个副本,即旧的虚拟 DOM 和重新渲染的虚拟 DOM,它是在调用 render() 方法时创建的。

render() 方法的输出是一个映射到 DOM 元素的 javascript 对象。当一个组件发生变化时,我们会得到一个新的 react 元素。然后,它将重新渲染的虚拟 DOM 中的新反应元素及其子元素与旧虚拟 DOM 中的元素及其子元素进行比较。如果发现任何差异,它只会在发生变化的地方更新真实的 DOM(例如按钮的文本发生了变化),而不是更新整个真实的 DOM。如果没有发现差异,则不会触及真正的 DOM。

【讨论】:

以上是关于react如何更新DOM的一部分?的主要内容,如果未能解决你的问题,请参考以下文章

react 中 虚拟DOM 和 Diff算法

如何实现 React 中的虚拟 DOM (下)

如何在提交表单后更新React.js中的DOM

react中的核心概念

React 的 Virtual DOM 如何比 DOM 快?

如何使用 React router-dom Link 跳转到特定部分