You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
exportfunctionupdateContainerAtExpirationTime(element: ReactNodeList,// <App />container: OpaqueRoot,parentComponent: ?React$Component<any,any>,expirationTime: ExpirationTime,callback: ?Function,){// TODO: If this is a nested container, this won't be the root.constcurrent=container.current;if(__DEV__){
...
}// 目前版本React拿不到context,因为 parentComponent 为nullconstcontext=getContextForSubtree(parentComponent);if(container.context===null){container.context=context;}else{container.pendingContext=context;}returnscheduleRootUpdate(current,element,expirationTime,callback);}functionscheduleRootUpdate(current: Fiber,element: ReactNodeList,expirationTime: ExpirationTime,callback: ?Function,){if(__DEV__){
...
}// update对象是用来标记React应用中需要更新的节点constupdate=createUpdate(expirationTime);// Caution: React DevTools currently depends on this property// being called "element".// 设置update的相关属性update.payload={element};callback=callback===undefined ? null : callback;if(callback!==null){warningWithoutStack(typeofcallback==='function','render(...): Expected the last optional `callback` argument to be a '+'function. Instead received: %s.',callback,);update.callback=callback;}// 把update加入到 fiber 的updateQueue 里,一个节点上可能会产生很多次更新,需要 batchUpdates (批量更新)enqueueUpdate(current,update);// 有更新产生,告诉 React 开始调度scheduleWork(current,expirationTime);returnexpirationTime;}
React 创建更新的过程
创建更新的方式
初始渲染
ReactDOM.render 、ReactDOM.hydrate
组件内更新
setState
forceUpdate
replaceState(即将被舍弃)
ReactDom.render
步骤
初始渲染
ReactDOM对象有
render
、hydrate
两个方法,render
方法是用在浏览器环境内,hydrate
用于服务端渲染,区别在于调用legacyRenderSubtreeIntoContainer
方法第四个参数false
和true
.legacyRenderSubtreeIntoContainer
作用主要是生成ReactRoot
并调用ReactRoot
实例的render
方法legacyCreateRootFromDOMContainer
函数的作用判断是不是hydrate
渲染,ReactDOM.render
当然为false
,接着会判断rootElement
有没有ROOT_ATTRIBUTE_NAME
即data-reactroot
属性来判断是不是服务端渲染,如果不是则 while 循环将 root 所有子节点全部删掉,返回new ReactRoot(container, isConcurrent, shouldHydrate)
接着看
ReactRoot
构造函数,构造函数里调用了 ReactFiberReconciler 里的createContainer
方法,这个方法调用createFiberRoot
生成一个FiberRoot
对象,最后挂载到实例的_internalRoot
上,legacyRenderSubtreeIntoContainer
方法里root.render
调用的最终ReactRoot
构造函数的protoType
上定义了render
方法,而它调用的是 ReactFiberReconciler 里的updateContainer
。DOMRenderer.updateContainer
中计算出一个expirationTime
传入了updateContainerAtExpirationTime
.FiberRoot
和RootFiber
接下来会讲到,先看updateContainerAtExpirationTime
创建更新的过程,调用scheduleRootUpdate
方法将RootFiber
、element
、计算出的expirationTime
、callback
传入,在这个方法里,首先会调用createUpdate
创建一个update
对象,enqueueUpdate
方法将update
对象加入到fiber
对象上的updateQueue
里,scheduleWork
即开始执行调度。创建更新的过程到此为止。ReactDOM.render 总结
初次渲染 传入 APP 组件和 getElementById(root) 执行
ReactDOM.render
返回并执行legacyRenderSubtreeIntoContainer
legacyRenderSubtreeIntoContainer
方法调用legacyCreateRootFromDOMContainer
方法把 getElementById(root) 里的子节点清空,并把返回值new ReactRoot
挂载到 getElementById(root) 节点的 _reactRootContainer 属性上ReactRoot 生成实例时调用 react-reconcile 模块的 createContainer 传入 getElementById(root) 执行
createFiberRoot
生成一个FiberRoot
对象挂载到实例的 _internalRootlegacyRenderSubtreeIntoContainer 方法里
root.render
方法实际是调用 ReactRoot 原型上的render方法ReactRoot.prototype.render 把子节点和实例生成的 _internalRoot FiberRoot 对象传入 react-reconcile 模块的 updateContainer 中
在 updateContainer 中 react 计算出一个 expirationTime 传入 updateContainerAtExpirationTime 调用 scheduleRootUpdate 中做三件事
createUpddate 创建update对象来标记 react 需要更新的点
enqueueUpdate 将 update 加入到 RootFiber 的 updateQueue 中
scheduleWork 根据任务的优先级进行调度更新
下一篇
The text was updated successfully, but these errors were encountered: