1 )概述
completeWork
中 对 HostText
的处理2 )源码
定位到 packages/react-reconciler/src/ReactFiberCompleteWork.js#L663
到 case HostText
这里
case HostText: {
let newText = newProps;
// 符合这个条件,说明它不是第一次渲染,就是更新的状态
// 调用 updateHostText 进行更新
if (current && workInProgress.stateNode != null) {
const oldText = current.memoizedProps;
// If we have an alternate, that means this is an update and we need
// to schedule a side-effect to do the updates.
updateHostText(current, workInProgress, oldText, newText);
} else {
// 对于第一次渲染
if (typeof newText !== 'string') {
invariant(
workInProgress.stateNode !== null,
'We must have new props for new mounts. This error is likely ' +
'caused by a bug in React. Please file an issue.',
);
// This can happen when we abort work.
}
// 跳过 context 处理
const rootContainerInstance = getRootHostContainer();
const currentHostContext = getHostContext();
// 跳过 hydrate 处理
let wasHydrated = popHydrationState(workInProgress);
if (wasHydrated) {
if (prepareToHydrateHostTextInstance(workInProgress)) {
markUpdate(workInProgress);
}
} else {
// 创建 文本 实例
workInProgress.stateNode = createTextInstance(
newText,
rootContainerInstance,
currentHostContext,
workInProgress,
);
}
}
break;
}
进入 updateHostText
updateHostText = function(
current: Fiber,
workInProgress: Fiber,
oldText: string,
newText: string,
) {
// 这个非常简单,通过前后 text 是否有区别
// 如果不同,则创建新的 text实例
if (oldText !== newText) {
// If the text content differs, we'll create a new text instance for it.
// 先跳过 context 的处理
const rootContainerInstance = getRootHostContainer();
const currentHostContext = getHostContext();
workInProgress.stateNode = createTextInstance(
newText,
rootContainerInstance,
currentHostContext,
workInProgress,
);
// We'll have to mark it as having an effect, even though we won't use the effect for anything.
// This lets the parents know that at least one of their children has changed.
markUpdate(workInProgress);
}
};
createTextInstance
// packages/react-dom/src/client/ReactDOMHostConfig.js#L272
export function createTextInstance(
text: string,
rootContainerInstance: Container,
hostContext: HostContext,
internalInstanceHandle: Object,
): TextInstance {
if (__DEV__) {
const hostContextDev = ((hostContext: any): HostContextDev);
validateDOMNesting(null, text, hostContextDev.ancestorInfo);
}
const textNode: TextInstance = createTextNode(text, rootContainerInstance);
// 这个方法之前阅过
precacheFiberNode(internalInstanceHandle, textNode);
return textNode;
}
createTextNode
export function createTextNode(
text: string,
rootContainerElement: Element | Document,
): Text {
// 最终 getOwnerDocumentFromRootContainer 这里返回一个dom对象,调用dom的 createTextNode 这个方法
return getOwnerDocumentFromRootContainer(rootContainerElement).createTextNode(
text,
);
}
getOwnerDocumentFromRootContainer
function getOwnerDocumentFromRootContainer(
rootContainerElement: Element | Document,
): Document {
// rootContainerElement.ownerDocument 这里是 window.document 对象
// 这么做是为了兼容多平台api的使用
return rootContainerElement.nodeType === DOCUMENT_NODE
? (rootContainerElement: any)
: rootContainerElement.ownerDocument;
}
HostText 相比于 HostComponents 来说,它没有多种选择
没有各种各样的属性,整体来说非常的简单
一些特别说明的,写在了上述代码注释中