【JS】React和DOM的那些事-节点更新

React和DOM的那些事-节点更新

nero发布于 4 分钟前

点击进入React源码调试仓库。

React的更新最终要落实到页面上,所以本文主要讲解DOM节点(HostComponent)和文本节点(HostText)的更新,对于前者来说更新是props的更新,对后者来说更新是文字内容的更新。

commitWork是节点更新的入口。

function commitMutationEffectsImpl(

fiber: Fiber, root: FiberRoot, renderPriorityLevel,) {

...

switch (primaryEffectTag) {

...

case Update: {

const current = fiber.alternate;

commitWork(current, fiber);

break; } }}

commitWork重点处理了HostComponent和HostText。

HostText的更新

更新HostText,实际上也就是更新文本内容,过程比较简单,最终调用commitTextUpdate来设置文本内容。

function commitWork(current: Fiber | null, finishedWork: Fiber): void {

...

switch (finishedWork.tag) {

... case HostText: {

const textInstance: TextInstance = finishedWork.stateNode;

const newText: string = finishedWork.memoizedProps;

const oldText: string = current !== null ? current.memoizedProps : newText; commitTextUpdate(textInstance, oldText, newText);

return; } } ...}

HostComponent的更新

更新HostComponent是更新fiber节点上的props,这需要使用到在render阶段的complete过程中节点props的diff结果:fiber.updateQueue。再来回顾一下它的形式:数组,以2为单位,index为偶数的是key,为奇数的是value。

[ 'style', { color: 'blue' }, title, '测试标题' ]

整个更新过程就是遍历数组,最终调用updateDOMProperties将属性和值设置到DOM节点上。

function updateDOMProperties(

domElement: Element,

updatePayload: Array<any>,

wasCustomComponentTag: boolean, isCustomComponentTag: boolean,): void {

// 遍历updateQueue数组,应用更新

for (let i = 0; i < updatePayload.length; i += 2) {

const propKey = updatePayload[i]; const propValue = updatePayload[i + 1]; if (propKey === STYLE) {

setValueForStyles(domElement, propValue);

} else if (propKey === DANGEROUSLY_SET_INNER_HTML) { setInnerHTML(domElement, propValue);

} else if (propKey === CHILDREN) { setTextContent(domElement, propValue);

} else { setValueForProperty(domElement, propKey, propValue, isCustomComponentTag);

} }}

总结

整个节点的更新过程比较单纯,将新的属性值或者新的文本内容设置到节点上,并不涉及其他复杂的操作,比较好理解。

欢迎扫码关注公众号,发现更多技术文章
【JS】React和DOM的那些事-节点更新

javascript前端react.js

阅读 12更新于 3 分钟前

本作品系原创,采用《署名-非商业性使用-禁止演绎 4.0 国际》许可协议


React的秘密

最平实的语言,解读复杂React

avatar

nero

前端工程师

3.5k 声望

1.8k 粉丝

0 条评论

得票时间

avatar

nero

前端工程师

3.5k 声望

1.8k 粉丝

宣传栏

点击进入React源码调试仓库。

React的更新最终要落实到页面上,所以本文主要讲解DOM节点(HostComponent)和文本节点(HostText)的更新,对于前者来说更新是props的更新,对后者来说更新是文字内容的更新。

commitWork是节点更新的入口。

function commitMutationEffectsImpl(

fiber: Fiber, root: FiberRoot, renderPriorityLevel,) {

...

switch (primaryEffectTag) {

...

case Update: {

const current = fiber.alternate;

commitWork(current, fiber);

break; } }}

commitWork重点处理了HostComponent和HostText。

HostText的更新

更新HostText,实际上也就是更新文本内容,过程比较简单,最终调用commitTextUpdate来设置文本内容。

function commitWork(current: Fiber | null, finishedWork: Fiber): void {

...

switch (finishedWork.tag) {

... case HostText: {

const textInstance: TextInstance = finishedWork.stateNode;

const newText: string = finishedWork.memoizedProps;

const oldText: string = current !== null ? current.memoizedProps : newText; commitTextUpdate(textInstance, oldText, newText);

return; } } ...}

HostComponent的更新

更新HostComponent是更新fiber节点上的props,这需要使用到在render阶段的complete过程中节点props的diff结果:fiber.updateQueue。再来回顾一下它的形式:数组,以2为单位,index为偶数的是key,为奇数的是value。

[ 'style', { color: 'blue' }, title, '测试标题' ]

整个更新过程就是遍历数组,最终调用updateDOMProperties将属性和值设置到DOM节点上。

function updateDOMProperties(

domElement: Element,

updatePayload: Array<any>,

wasCustomComponentTag: boolean, isCustomComponentTag: boolean,): void {

// 遍历updateQueue数组,应用更新

for (let i = 0; i < updatePayload.length; i += 2) {

const propKey = updatePayload[i]; const propValue = updatePayload[i + 1]; if (propKey === STYLE) {

setValueForStyles(domElement, propValue);

} else if (propKey === DANGEROUSLY_SET_INNER_HTML) { setInnerHTML(domElement, propValue);

} else if (propKey === CHILDREN) { setTextContent(domElement, propValue);

} else { setValueForProperty(domElement, propKey, propValue, isCustomComponentTag);

} }}

总结

整个节点的更新过程比较单纯,将新的属性值或者新的文本内容设置到节点上,并不涉及其他复杂的操作,比较好理解。

欢迎扫码关注公众号,发现更多技术文章
【JS】React和DOM的那些事-节点更新

以上是 【JS】React和DOM的那些事-节点更新 的全部内容, 来源链接: utcz.com/a/107427.html

回到顶部