React提供了声明式的API,以致于咱们不须要担忧每次更新具体发生了什么更改。这使得咱们开发应用变得很容易,但始终没法清楚React内部是如何实现的。本文解释了在 “差分算法” 中如何作出选择,使得组件更新,在足够快的高性能应用中仍然能够预测。html
在理解 “差分算法” 以前,首先咱们须要去理解:node
render()
函数的做用与生命周期;ReactDOM.render()
函数的做用;import React from "react";
import ReactDOM from 'react-dom';
const First = () => (<div> <h1>第一棵树</h1> <div>附加信息</div> </div>);
const Second = () => (<div> <h1>第二棵树</h1> <Third /> </div>);
const Third = () => (<div> <h1>第三棵树</h1> <div>附加信息</div> </div>);
const App = () => (<div> <First /> <Second /> </div>);
ReactDOM.render(<App />, document.getElementById('root')); 复制代码
万变不离其宗,对于一个HTML页面,document与Node永远会是它的基础组成部分(实际上document也只是一个特别的Node),若是把document看作一张纸,那么Node能够当作点缀在纸上的文字、图片或符号。react
在React中,React组件是由真实的Dom Node组成,最终会被转化为Dom Node并在document中渲染出来(事件\样式\选择器,只属于真实的DOM Node)。算法
当你使用React的时候,你能够认为:浏览器
render()
函数都建立了一棵React元素树。render()
函数,见下文。HTMLElement
组成,便是 —— 每一棵树均可以做为另外一棵树的子树,正如上图所示:<Third />是<Second />的子树,<Second />和<First />又都是<App />的子树。ReactDOM.render(element, container[, callback])
将这棵树挂载到容器(container)
中。容器(container)
,不过是document中某个指定的Div或其它块级元素。JavaScript选择器
仍是dom操做插件
仍是React提供的Refs
,对Dom node的操做都会被保留在这个document中,并在组件的state
或props
发生改变的时候参与 “差分算法”。对于Function组件(无状态组件)
就是自身,对于Class组件(有状态组件)
就是从React.Component
继承的render()
方法。服务器
当render()
被调用时,能够依赖props
和state
来构造返回值,其返回值类型包括以下:cookie
<div />
、<MyComponent />
render()
必须返回单元素(single),React提供了<></>和<React.Fragment>容许开发者从render()
中返回多元素test && <Child />
,这里test
是布尔值(boolean)render()
应该是一个纯函数,返回值只依赖于state
和props
,而且不会产生反作用,反作用包括:网络
state
和props
Date.now()
或 Math.random()
setTimeout()
、console.log()
若是你须要浏览器交互或网络请求,能够选择在componentDidMount()
或其它合适的声明周期函数中执行。有些条件没有作硬性要求,可是保证render()
做为纯函数,可以提升组件更新的性能。session
组件在挂载(Mounting)和更新(Updating)时,render()
都会被执行,并产生一棵新的React元素树。声明周期执行顺序以下。详情可见官方文档《component-lifecycle》dom
render()
会产生一棵新的树,这颗新树会被直接挂载到父组件对应的那棵树上。
render()
会产生一棵新的树,而后与先前的那棵旧树,执行 “ 差分算法” 更新UI(用户界面)。
ReactDOM.render(element, container[, callback])
复制代码
该方法将整个React元素树渲染到document中指定的<Div />
容器中,并返回根组件(对应最大元素树)的引用(Function 组件 —— 无状态组件,没有实例(Instance)因此返回null)。
若是这个React元素(根组件)先前已经被渲染到容器中,那么将对它执行更新,按照 “差分算法” 去呈现它。
若是这个可选的参数—— 回调函数,被提供。那么会在组件被渲染或更新后调用。
ReactDOM.render()
控制着容器(container)节点的内容,第一次调用时,任何存在的Dom元素都会被替换,以后再调用会使用React Dom diffing algorithm(差分算法)进行高效更新。ReactDOM.render()
不修改容器节点(只修改容器的子节点)。ReactDOM.render()
当前返回根组件(root ReactComponent )实例的引用。然而,返回值的使用已经被遗留了,应该避免去使用它,由于在将来的React版本中,在某些状况下React会采用异步的方式去渲染组件。若是你真的须要引用根组件实例,首选解决方案是为你的根组件添加《callback ref》。ReactDOM.render()
去融合服务端渲染容器(server-rendered container)已经被遗弃了,并将在React 17被移除,代替使用hydrate()。