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
/** * 客户端渲染 * @param element 表示一个ReactElement对象 * @param container 需要将组件挂载到页面中的DOM容器 * @param callback 渲染完成后需要执行的回调函数 */exportfunctionrender(element: React$Element<any>,container: Container,callback: ?Function){invariant(isValidContainer(container),"Target container is not a DOM element.");if(__DEV__){constisModernRoot=isContainerMarkedAsRoot(container)&&container._reactRootContainer===undefined;if(isModernRoot){console.error("You are calling ReactDOM.render() on a container that was previously "+"passed to ReactDOM.createRoot(). This is not supported. "+"Did you mean to call root.render(element)?");}}returnlegacyRenderSubtreeIntoContainer(null,element,container,false,callback);}
然后是hydrate方法:
/** * 服务端渲染 * @param element 表示一个ReactNode,可以是一个ReactElement对象 * @param container 需要将组件挂载到页面中的DOM容器 * @param callback 渲染完成后需要执行的回调函数 */exportfunctionhydrate(element: React$Node,container: Container,callback: ?Function){invariant(isValidContainer(container),"Target container is not a DOM element.");if(__DEV__){constisModernRoot=isContainerMarkedAsRoot(container)&&container._reactRootContainer===undefined;if(isModernRoot){console.error("You are calling ReactDOM.hydrate() on a container that was previously "+"passed to ReactDOM.createRoot(). This is not supported. "+"Did you mean to call createRoot(container, {hydrate: true}).render(element)?");}}// TODO: throw or warn if we couldn't hydrate?returnlegacyRenderSubtreeIntoContainer(null,element,container,true,callback);}
ReactDOM.render
首先来到
packages/react-dom/src/client/ReactDOM.js
文件:可以看到
render
、hydrate
方法定义在packages/react-dom/src/client/ReactDOMLegacy.js
文件中。首先来看
render
方法:然后是
hydrate
方法:可以看到:
render
方法和hydrate
方法在执行legacyRenderSubtreeIntoContainer
时,第一个参数的值均为null
,第四个参数的值恰好相反。我们来看
legacyRenderSubtreeIntoContainer
方法:这部分代码内容稍微有点多,相对也没那么好理解,我们暂时先不去看整个函数的完整内容。试想当我们第一次启动运行项目的时候,也就是第一次执行
ReactDOM.render
方法的时候,这时去获取container._reactRootContainer
肯定是没有值的,所以我们先关心第一个if
语句中的内容:这里通过调用
legacyCreateRootFromDOMContainer
方法将其返回值赋值给container._reactRootContainer
,我们来看legacyCreateRootFromDOMContainer
的具体实现:其中在
shouldHydrateDueToLegacyHeuristic
方法中,首先根据container
来获取DOM
容器中的第一个子节点,获取该子节点的目的在于通过节点的nodeType
和是否具有ROOT_ATTRIBUTE_NAME
属性来区分是客户端渲染还是服务端渲染。ROOT_ATTRIBUTE_NAME
位于packages/react-dom/src/shared/DOMProperty.js
文件中,表示data-reactroot
属性。我们知道,在服务端渲染中有别于客户端渲染的是,node
服务会在后台先根据匹配到的路由生成完整的HTML
字符串,然后再将HTML
字符串发送到浏览器端,最终生成的HTML
结构简化后如下:在客户端渲染中是没有
data-reactroot
属性的,因此就可以区分出客户端渲染和服务端渲染。React
中的nodeType
主要包含了五种,其对应的值和W3C
中的nodeType
标准是保持一致的,位于与DOMProperty.js
同级的HTMLNodeType.js
文件中:到这里,相信你一定可以很容易的区分出客户端渲染和服务端渲染。接下来我们将尝试去理解两个很容易混淆的概念:
FiberRoot
和RootFiber
。这两个概念在React
的整个任务调度过程中起着关键性的作用,如果不理解这两个概念,后续的任务调度过程就是空谈,所以这里也是我们必须要去理解的部分。The text was updated successfully, but these errors were encountered: