基于文章 实现 React Fragment 节点渲染。
本文将介绍如何渲染类组件。
类组件已不推荐使用,本文不会讲太多。
js
class ClassComponent extends Component {
render() {
return (
<div>
<h3>ClassComponent</h3>
</div>
)
}
}
初始化 Component
js
export function Component(props: any) {
this.props = props;
}
// 区分类组件和函数组件
Component.prototype.isReactComponent = {}
Render 阶段
BeginWork 阶段
beginWork
函数增加类组件的 case。
js
function updateClassComponent(current: Fiber | null, workInProgress: Fiber) {
const { type, pendingProps } = workInProgress;
const instance = new type(pendingProps);
const children = instance.render();
reconcileChildren(current, workInProgress, children);
return workInProgress.child;
}
// 1. 处理当前 fiber,因为不同组件对应的 fiber 处理方式不同,
// 2. 返回子节点 child
export function beginWork(
current: Fiber | null,
workInProgress: Fiber
): Fiber | null {
switch (workInProgress.tag) {
// 根节点
case HostRoot:
return updateHostRoot(current, workInProgress);
// 原生标签,div、span...
case HostComponent:
return updateHostComponent(current, workInProgress);
// 文本节点
case HostText:
return updateHostText(current, workInProgress);
// Fragment
case Fragment:
return updateHostFragment(current, workInProgress);
case ClassComponent:
return updateClassComponent(current, workInProgress);
}
throw new Error(
`Unknown unit of work tag (${workInProgress.tag}). This error is likely caused by a bug in ` +
"React. Please file an issue."
);
}
createFiberFromTypeAndProps
函数,增加类组件的 case。
js
// 根据 TypeAndProps 创建fiber
export function createFiberFromTypeAndProps(
type: any,
key: null | string,
pendingProps: any
) {
let fiberTag: WorkTag = IndeterminateComponent;
if (isFn(type)) {
// 函数组件
if (type.prototype.isReactComponent) {
fiberTag = ClassComponent;
}
} else if (isStr(type)) {
// 原生标签
fiberTag = HostComponent;
} else if (type === REACT_FRAGMENT_TYPE) {
fiberTag = Fragment;
}
const fiber = createFiber(fiberTag, pendingProps, key);
fiber.elementType = type;
fiber.type = type;
return fiber;
}
Complete 阶段
completeWork
函数增加类组件的 case。
js
function completeWork(
current: Fiber | null,
workInProgress: Fiber
): Fiber | null {
const newProps = workInProgress.pendingProps;
switch (workInProgress.tag) {
case Fragment:
case HostRoot:
case ClassComponent:{
return null;
}
case HostComponent: {
// 原生标签,type 是标签名
const { type } = workInProgress;
// 1. 创建真实 DOM
const instance = document.createElement(type);
// 2. 初始化 DOM 属性
finalizeInitialChildren(instance, newProps);
// 3. 把子 dom 挂载到父 dom 上
appendAllChildren(instance, workInProgress);
workInProgress.stateNode = instance;
return null;
}
case HostText: {
workInProgress.stateNode = document.createTextNode(newProps);
return null;
}
}
throw new Error(
`Unknown unit of work tag (${workInProgress.tag}). This error is likely caused by a bug in ` +
"React. Please file an issue."
);
}