Function Component
1 )概述
FunctionComponent 会引出调和子节点的过程- 调和子节点是一个统一的过程,和各类组件不同类型没有太大关系
- 在 ReactDOM.render 第一次时,只有一个Fiber对象
- 这个Fiber对象它会保存它的props, 里面有很多的children
- 里面的 props.children 是 App 对应的 ReactElement
- 这个 ReactElement 不是 Fiber 对象,肯定要去创建它的Fiber对象
- 在 ReactDom.render 的过程中, 是一步一步的往下执行
- 对于children,肯定要判断 ReactElement 的类型
- 基于不同类型做对应的处理方式,这个过程肯定是非常重要的
2 )源码
定位到 packages/react-reconciler/src/ReactFiberBeginWork.js
的 beginWork 函数,在 beginWork 下面的 执行 switch case 中
// beginWork 函数中的截取部分 case FunctionComponent: { // 这里的 type 就是 ReactElement 里面存储的 type 属性 // 这个 type 属性里面存储的就是 组件,如果是dom原生组件就是字符串 // 如果组件是 function component 就是一个方法,如果是 class component 它就是类 const Component = workInProgress.type; // pendingProps 是新渲染的时候产生的 props,这个和调和子节点有关系 const unresolvedProps = workInProgress.pendingProps; // 这个 resolvedProps 是和 Suspense 组件有关的,throw 的是一个 Promise 可能会resolve出一些东西 // 可以先默认 resolvedProps 就是上面的 unresolvedProps const resolvedProps = workInProgress.elementType === Component ? unresolvedProps : resolveDefaultProps(Component, unresolvedProps); return updateFunctionComponent( current, workInProgress, Component, resolvedProps, renderExpirationTime, ); }
进入到 updateFunctionComponent 方法
function updateFunctionComponent( current, workInProgress, Component, nextProps: any, renderExpirationTime, ) { // 获取两个 context 先跳过 const unmaskedContext = getUnmaskedContext(workInProgress, Component, true); const context = getMaskedContext(workInProgress, unmaskedContext); let nextChildren; prepareToReadContext(workInProgress, renderExpirationTime); // 跳过 DEV 相关 if (__DEV__) { ReactCurrentOwner.current = workInProgress; ReactCurrentFiber.setCurrentPhase('render'); nextChildren = Component(nextProps, context); ReactCurrentFiber.setCurrentPhase(null); } else { // 这里的 Component 就是组件的方法 // 调用 Component 方法的时候传入 nextProps, context 两个参数 // context 这个在 官网API文档中没有提及 // 可以在 function component 中获取到 child组件的 contextTypes 属性,也就是组件加上这个属性并配置props // 组件内就可以获取上层传递过来的 context nextChildren = Component(nextProps, context); } // React DevTools reads this flag. // 注意这里 workInProgress.effectTag |= PerformedWork; reconcileChildren( current, workInProgress, nextChildren, renderExpirationTime, ); // 这里 return 的是 child, 说明 在 reconcileChildren 很可能处理 child return workInProgress.child; }
- 关于
workInProgress.effectTag |= PerformedWork; 这种操作- 在 ReactEffectTags.js 文件中, 有所有可能产生effect的值
- 这里都是二进制的,每个值的1所在位置都是不一样的
- 通过逻辑操作,&, | 的联合判断是否有某个特性
- 上面 PerformedWork 本质是没有什么意义的
- 是给 DevTools 说明这个组件在渲染中有更新
- 关于 reconcileChildren 是通用的调节子节点的核心流程,这块先跳过