React学习笔记(三)——React源码

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wuqingdeqing/article/details/85848170

3.1 初步

React源码的组织结构如下:

其中renderers是React代码的核心部分,包含了大部分功能的实现。其结构如下:

3.2 Virtual DOM模型

该模型负责Virtual DOM底层框架的构建工作,它拥有一整套的Virtual DOM标签,并负责虚拟节点及其属性的构建、更新、删除等工作。

3.2.1 创建React元素

创建过程如下:

const Nav, Profile;

//输入(JSX)
const app = <Nav color="blue"><Profile>click</Profile></Nav>;

//输出(JS)
const app = React.createElement(
	Nav;
	{color:"blue"},
	React.createElement(Profile, null, "click")
);

3.2.2 初始化组件入口

当使用React创建组件时,首先会调用instantiateReactComponent,这是初始化组件的入口函数,它通过判断Node类型来区分不同组件的入口。如下图:

3.2.3 文本组件

当Node类型为文本节点时不算Virtual DOM元素,但React为了保持渲染的一致性,将其封装为文本组件ReactDOMTextComponent。如下图:

3.2.4 DOM标签组件

使用React时,使用的标签并不是原生标签,其实是React生成的Virtual DOM对象,只不过标签名称相同罢了。

扫描二维码关注公众号,回复: 5096201 查看本文章

ReactDOMComponent针对Virtual DOM标签的处理主要分为以下两个部分:属性的更新和子节点的更新。

3.2.5 自定义组件

ReactCompositeComponent自定义组件实现了一整套React生命周期和setState机制,因此自定义组件是在生命周期的环境中进行更新属性、内容和子节点的操作。

3.3 生命周期

React主要思想是通过构建可复用组件来构建用户界面。所谓组件,其实就是有限状态机,通过状态渲染对应的界面,且每个组件都有自己的生命周期,它规定了组件的状态和方法需要在哪个阶段执行和改变。

3.3.1 初探

生命周期的执行顺序如下图所示:

3.2.2 详解

生命周期的三个阶段:

3.2.3 无状态组件

无状态组件没有状态,没有生命周期,只是简单地接受props渲染生成的DOM结构,是一个纯粹为渲染而生的组件。由于无状态组件有简单、便捷、高效等特点,所以应尽量使用。

3.4 setState机制

React通过this.state来访问state,通过this.setState()方法来更新state。当this.setState()被调用时,React会重新调用render方法来重新渲染UI。

3.4.2 setState异步更新

setState通过一个队里机制实现state更新。当执行setState时,会需要将更新的state合并后放入状态队列,而不会立即更新this.state,队列机制可以批量地高效更新state。如果不通过setState而直接修改this.state的值,那么该state将不会被放入状态队列中,当下次调用setState并对状态队列进行合并时,将会忽略之前直接被修改的state,而造成无法预知的错误。

3.4.2 setState循环调用风险

如下图所示:

3.4.3 setState调用栈

其简化调用栈如下图:

3.5 diff算法

diff会计算出Virtual DOM中真正变化的部分,并只针对该部分进行原生DOM操作,而非重新渲染整个页面,从而保证了每次操作更新后页面的高效渲染。

React diff算法的3个策略。

策略一:Web UI中DOM节点跨层级移动操作特别少,可以忽略不计。

策略二:拥有相同类的两个组件将会生成相似的树形结构,拥有不同类的两个组件将会生成不同的树形结构。

策略三:对于同一层级的一组子节点,它们可以通过唯一id进行区分。

基于以上策略,React分别对tree diff,component diff以及element diff进行算法优化。

3.6 React Patch方法

Patch是将tree diff计算出来的DOM差异队列更新到真实的DOM节点上,最终让浏览器可以渲染出更新的数据。Patch帮助浏览器识别Virtual DOM。它的实现非常简洁明了,主要是通过遍历差异队列实现的。遍历差异队列时,通过更新类型进行相应的操作,包括:新节点的插入、已有节点的移动和移除等。

猜你喜欢

转载自blog.csdn.net/wuqingdeqing/article/details/85848170
今日推荐