前言:为了搞清楚react到底是个什么样的“框架”以及它的内部机制,因此开始阅读react源码。在阅读源码的时候,为了梳理流程,根据自己的理解以及网上的一些资料做了一些(大致流程的)笔记。笔记是当时的理解,写的时候,仍然有很多不理解的地方待后续完善。而写出来的部分,可能会有很多理解不到位甚至是错误的地方,一旦有新的理解或者发现了错误,会补充与修正。
react源码版本:16.8.6
ReactDOM.render用法:
import ReactDOM from 'react-dom';
ReactDOM.render(<App />, document.getElementById('root));
ReactDOM.render源码(这里只摘录了主要代码):
代码路径:packages/react-dom/src/client/ReactDOM.js
const ReactDOM: Object = {
...
render(
element: React$Element<any>, // React Element,也就是上面的<App />
container: DOMContainer, // 一个dom节点,也就是上面的root
callback: ?Function, // 回调函数,可不传
) {
...
return legacyRenderSubtreeIntoContainer(
null,
element,
container,
false,
callback,
);
},
...
可以看到这里调用了legacyRenderSubtreeIntoContainer函数并返回,然后找到该函数源码。
legacyRenderSubtreeIntoContainer函数代码:
代码路径:packages/react-dom/src/client/ReactDOM.js
// 将子组件树渲染进container中
function legacyRenderSubtreeIntoContainer(
parentComponent: ?React$Component<any, any>, // 父组件,这里传入的是null
children: ReactNodeList, // 子节点,这里是上面传入的<App />
container: DOMContainer, // 这里是root节点
forceHydrate: boolean, // 是否进行组合,render传入的是false
callback: ?Function, // 上面的回调函数
) {
...
// TODO: Without `any` type, Flow says "Property cannot be accessed on any
// member of intersection type." Whyyyyyy.
// 这里是初次渲染,container上没有_reactRootContainer属性,root为false
let root: Root = (container._reactRootContainer: any);
if (!root) {
// 初次挂载
root = container._reactRootContainer = legacyCreateRootFromDOMContainer(
container,
forceHydrate,
);