还处于初级学习阶段,懵懵懂懂,边学习边将自己的理解记录下来,后期随着理解的深入会不断回过头来完善。
ReactDOM.render
ReactDOM.render是渲染组件的第一步,接收三个参数:第一个是createElement创建出来的ReactElement,第二个是dom容器,用来存放ReactElement,第三个是回调函数,用于组件装载后执行的操作。
这个函数做的事情:它会调legacyRenderSubtreeIntoContainer,并将所有参数传给这个函数。然后后面的关键性操作就可以去legacyRenderSubtreeIntoContainer这里面看了。
render( element: React$Element<any>, container: DOMContainer, callback: ?Function, ) { return legacyRenderSubtreeIntoContainer( null, element, container, false, callback, ); }
legacyRenderSubtreeIntoContainer
这个函数做的事情:
看container里有没有_reactRootContainer,我们这里先分析初次进来的情况,初次进来肯定是没有的,所以会去执行legacyCreateRootFromDOMContainer,legacyCreateRootFromDOMContainer里还会调用别的函数,兜兜转转返回一个FiberRoot。
再往下看,parentComponent传进来的就是null,所以直接执行root.render,即ReactRoot.render这个方法。
function legacyRenderSubtreeIntoContainer( parentComponent: ?React$Component<any, any>, children: ReactNodeList, container: DOMContainer, forceHydrate: boolean, callback: ?Function, ) { let root: Root = (container._reactRootContainer: any); if (!root) { // Initial mount root = container._reactRootContainer = legacyCreateRootFromDOMContainer( // 返回一个FiberRoot container, forceHydrate, ); // Initial mount should not be batched.这里还不懂,后面会学到 unbatchedUpdates(() => { if (parentComponent != null) { root.legacy_renderSubtreeIntoContainer( parentComponent, children, callback, ); } else { root.render(children, callback); } }); } return getPublicRootInstance(root._internalRoot); }
ReactRoot.render
这个函数做的事情:执行updateContainer
ReactRoot.prototype.render = function( children: ReactNodeList, callback: ?() => mixed, ): Work { const root = this._internalRoot; const work = new ReactWork(); callback = callback === undefined ? null : callback; if (__DEV__) { warnOnInvalidCallback(callback, 'render'); } if (callback !== null) { work.then(callback); } updateContainer(children, root, null, work._onCommit); return work; };
updateContainer
这个函数做的事情:计算当前时间,超时时间,并传给updateContainerAtExpirationTime
export function updateContainer( element: ReactNodeList, container: OpaqueRoot, parentComponent: ?React$Component<any, any>, callback: ?Function, ): ExpirationTime { const current = container.current; const currentTime = requestCurrentTime(); const expirationTime = computeExpirationForFiber(currentTime, current); return updateContainerAtExpirationTime( element, container, parentComponent, expirationTime, callback, ); }
updateContainerAtExpirationTime
这个函数做的事情:执行scheduleRootUpdate,到这里我已经不明白了。
export function updateContainerAtExpirationTime( element: ReactNodeList, container: OpaqueRoot, parentComponent: ?React$Component<any, any>, expirationTime: ExpirationTime, callback: ?Function, ) { // TODO: If this is a nested container, this won't be the root. const current = container.current; const context = getContextForSubtree(parentComponent); if (container.context === null) { container.context = context; } else { container.pendingContext = context; } return scheduleRootUpdate(current, element, expirationTime, callback); }
scheduleRootUpdate
从这里开始我也不明白了,总之是调用scheduleWork,开始调度了。
function scheduleRootUpdate( current: Fiber, element: ReactNodeList, expirationTime: ExpirationTime, callback: ?Function, ) { const update = createUpdate(expirationTime); // Caution: React DevTools currently depends on this property // being called "element". update.payload = {element}; callback = callback === undefined ? null : callback; flushPassiveEffects(); enqueueUpdate(current, update); scheduleWork(current, expirationTime); // 最最最复杂的一块,开始调度 return expirationTime; }