React渲染 - 流程概述

导语 web前端技术中,有个叫作jsx的模板渲染语法,它是一个JavaScript 的语法扩展,目前逐渐被行业标准化(用的人多了...)。实际上jsx 是来源于一个前端框架 react。在react中除了咱们了解的jsx,那么jsx在react的渲染过程是哪一个环节生效,以及渲染过程经历了哪些步骤。本文会基于这些点进行概述。前端

介绍前的建议

1.本文附上了react.render树状图.xmind,此为做者查看/调试react的渲染源码时作的结构笔记。能够下载进行一些函数定位,一些函数代码位置较深且存在部分依赖,以此关联上下文是个不错的选择。react

2.做者是基于17版本的react进行解读与调试 -- github.com/facebook/re…webpack

3.设置了几个大标题,提早介绍一下有关react的函数,2、三 目录可直接跳过。git

React中用到的一些Object设置对象属性方法

React中自带的经常使用方法

React中的经常使用名词

jsx简述

好比以下代码:github

ReactDOM.render(
<div> <h1>Hello, world!</h1> <p>React to Render</p> </div>
,
document.getElementById('root')
);
复制代码

这样就简单完成了页面的渲染。这其中经历了:web

1.jsx通过babel打包转换成js语法 (@babel/helper-builder-react-jsx-experimental)浏览器

2.react执行render函数,进行节点的遍历渲染并绑定事件前端框架

若是拿刚才上述的代码进行babel转换,那么能够获得以下具体执行的jscode:微信

ReactDOM.render( 
    /*#__PURE__*/
    React.createElement("div",
    null, 
    /*#__PURE__*/
    React.createElement("h1", null, "Hello, world!"),
    /*#__PURE__*/ 
    React.createElement("p", null, "React to Render")), 
    document.getElementById('root')
 );
复制代码

附上一个在线jsx转换地址: babeljs.io/repl/babel

若是同窗们须要了解具体的转换语法,能够从 @babel/preset-react 中入口寻找依赖,具体的实如今 @babel/helper-builder-react-jsx-experimental、@babel/helper-plugin-utils

做者仅简单关联了上下文,这里稍做截图:

咱们会在webpack打包后的代码中看到 "_source","jsxFileName" 关键字。

这里的@babel/helper-plugin-utils还有一个做用:dev环境时在打包过程当中 输出文件代码块的位置,以便于调试定位,处理会返回输出的一个只读属性 "__source",其中包含 { fileName:path, lineNumber:number, columnNumber:number }

因此,jsx语法与渲染的执行代码没有存在关联,react经过babel转换成原生js进行处理执行。转换后的createElement即为建立节点。

建立节点

建立节点的入口代码在 "react/src/React.js" createElement函数

createElement会根据当前的环境,引用不一样的建立函数

图片

不过,开发版与产品版仅是一些有没有验证合法性,和是否输出错误内容的区别。最终都会建立一样的element对象 -- 虚拟节点

以下图所示:

图片

图上面右侧的错误提示中,用到的

图片

"filename,lineNumber"即在打包过程当中 @babel/helper-plugin-utils 提早注入好对象属性

当执行 真正的建立节点时 "ReactElement.js/createElement",这里会生成一个带有一些标记属性的Node对象:

图片

渲染

渲染能够按照功能,切分为三个点 准备、执行、提交。

render函数在 "/react-dom/src/client/ReactDOMLegacy.js"中,在进行一系列检查判断后最终会在legacyRenderSubtreeIntoContainer函数下执行渲染

legacyRenderSubtreeIntoContainer函数会执行如下三个步骤 :

图片

代码大体截图:

图片

咱们按照3个步骤往下延伸:

1-准备阶段:

作两件事:

1.建立根节点的一些关联对象 ReactRoot、fiberRoot、(HostRoot)fiberNode

2.定义根节点的默认浏览器事件

以下图,此为根节点(root)的关联对象

图片

关联对象具有以下一些属性及功能

图片

以下图,定义的默认事件:

图片

准备阶段总结以下:

图片

2 - 执行阶段 :

代码入口在 "react-reconciler/src/ReactFiberReconciler.js" unbatchedUpdates函数中

此阶段给全部的节点生成好节点树,等待提交

以下图所示:

图片

3 - 提交阶段:

提交阶段的代码也在 "react-reconciler/src/ReactFiberReconciler.js" unbatchedUpdates函数内执行

具体的函数执行在 "react-reconciler/src/ReactFiberWorkLoop.new.js" performSyncWorkOnRoot函数下执行 commitRoot

进行实际的执行Dom操做、部分周期函数

以下图所示:

图片

最终在 commitBeforeMutationEffects 和 commitMutationEffects 执行真正的dom操做和事件提交

总体的渲染流程到提交阶段执行完以后页面就已经可以看到效果,剩下的动做作一些数据同步、重设标记时间等..

图片

原做者: 陈碧松

未经赞成,禁止转载!

更多精彩内容,尽请关注腾讯VTeam技术团队微信公众号和视频号

相关文章
相关标签/搜索