react render过程
2019-03-12 本文已影响0人
JiangHaoFunc
1.入口文件中 ReactDOM.render 会把我们创建的react组件转换成真实的dom元素
ReactDOM.render(
<App />,
document.getElementById('root')
);
编译后会调用createElement方法,即
ReactDOM.render(
React.createElement(App),
document.getElementById('root')
);
于是,可以提出两个疑问
a.ReactDOM.render 方法中如何转成真实dom
b.React.createElement 方法中如何实例化react组件(虚拟dom)
2.createElement
这段代码很好理解,就是把传入的参数重新组装props,返回ReactElement
return ReactElement(
type,
key,
ref,
self,
source,
ReactCurrentOwner.current,
props,
);
3.ReactElement
最终创建的react对象
const element = {
// This tag allows us to uniquely identify this as a React Element
$$typeof: REACT_ELEMENT_TYPE,
// Built-in properties that belong on the element
type: type,
key: key,
ref: ref,
props: props,
// Record the component responsible for creating this element.
_owner: owner,
};
4.ReactDom.render
创建出了react对象然后通过render(element, container, callback)转换
// 把subtree(element)渲染到container中
return legacyRenderSubtreeIntoContainer(
null,
element,
container,
false,
callback,
);
5.legacyRenderSubtreeIntoContainer
该方法去获取root(没有就创建)
然后返回getPublicRootInstance
return getPublicRootInstance(root._internalRoot);
创建root:legacyCreateRootFromDOMContainer
createContainer就是去创建一个fiber tree
function ReactRoot(
container: DOMContainer,
isConcurrent: boolean,
hydrate: boolean,
) {
const root = createContainer(container, isConcurrent, hydrate);
this._internalRoot = root;
}
(如果root是第一次创建 初始化的进程不能批量运行(翻译!))
legacy_renderSubtreeIntoContainer也与fiber相关
// Initial mount should not be batched.
unbatchedUpdates(() => {
if (parentComponent != null) {
root.legacy_renderSubtreeIntoContainer(
parentComponent,
children,
callback,
);
} else {
root.render(children, callback);
}
});
创建好后,调用root.render(children, callback)方法把生成的fiber tree转换成真实dom,转换过程是react16推出的Fiber,可以先大概理解一下Fiber的原理。
最后的结果是performUnitOfWork=>completeUnitOfWork=>completeWork=>createInstance
处理这颗fiber tree,将其转换为真实DOM。转换的过程实质上也是循环递归,把虚拟dom的react对象转换成浏览器可以读的dom对象(document.createElement...)。
如果想继续深究,就需要理解fiber做了什么,好吧,我水平不够。。。理解的不是很透彻。