Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

leetcode-js/react/12 #10

giscus[bot] bot announced in Announcements
May 29, 2024 · 2 comments · 1 reply
Discussion options

leetcode-js/react/12

  1. 实现 Diff 算法 摘要 Diff 算法简介 实现单节点 Diff 实现多节点 Diff 处理 commit 阶段 相关代码可在 git tag v1.12 查看

https://2xiao.github.io/leetcode-js/react/12.html

You must be logged in to vote

Replies: 2 comments 1 reply

Comment options

你好 我想请教下
appendPlacementNodeIntoContainer 方法中有一个if判断,
if判断 dom类型的fiber节点,
else中如果是个 函数 fiber节点,遍历子节点。那么 之前if中append的节点 不是会重新append 一边吗?

You must be logged in to vote
1 reply
Comment options

2xiao Oct 16, 2024 — with giscus
Maintainer

appendPlacementNodeIntoContainer 的作用是将完成渲染的 FiberNode 以及其子节点,插入到 DOM 容器中,分两种情况:

  • 如果 finishedWorkHostComponentHostText(即 DOM 节点或文本节点),则进行移动或插入操作;

  • 如果 finishedWork 有子节点,且该节点不是 HostComponentHostText 类型,说明它是某种复合组件,通常是自定义的 React 组件或某些内部的特殊节点(例如 FragmentContextProvider 等)。这些节点本身不会直接对应 DOM 元素,因此需要递归遍历其子节点,直到找到可以映射到真实 DOM(即 HostComponentHostText)的节点。

举个例子,以下 React 组件结构:

function MyComponent() {
 return (
 <div>
 <span>Hello</span>
 <>World</>
 </div>
 );
}

React 组件返回的 JSX 包含一个空的 Fragment(<>World</>)。这个情况下,React Fiber 树中会有一个 Fragment 节点,但它不会直接映射到实际的 DOM 元素。

MyComponent 的 Fiber 树结构会像这样:

  • finishedWork(MyComponent 的 Fiber)
    • child<div> 的 Fiber(HostComponent)
      • child<span> 的 Fiber(HostComponent)
        • child → "Hello" 的 Fiber(HostText)
      • siblingFragment 的 Fiber
        • child → "World" 的 Fiber(HostText)

遍历过程:

  1. MyComponent 的 Fiber:

    • finishedWork.tag 不是 HostComponentHostText,因此不会直接插入到 DOM 中。
    • 递归处理 MyComponentchild,即 <div> 的 Fiber。
  2. <div> 的 Fiber:

    • finishedWork.tagHostComponent,表示这是一个真实的 DOM 元素(<div>)。
    • appendChildToContainer<div> 插入到 hostParent 容器中。
  3. 递归处理 <div> 的子节点:

    • 处理 <div>child,即 <span> 的 Fiber。
    • <span>HostComponent,它被插入到 <div> 中。
    • 递归处理 span 的子节点——文本节点 "Hello"。
  4. 处理文本节点 "Hello" 的 Fiber:

    • finishedWork.tagHostText,表示这是一个文本节点,它直接插入到 <span> 中。
  5. 处理 Fragment 的 Fiber:

    • FragmentFiber 节点(<>World</>)不会映射到 DOM,因为它仅用于结构化子节点。
    • 继续递归处理 Fragmentchild,即文本节点 "World"。
  6. 处理文本节点 "World" 的 Fiber:

    • FiberHostText 类型,表示它是一个文本节点,因此被插入到 <div> 中,作为最后一个子节点。

最终的 DOM 结构如下:

<div>
 <span>Hello</span>
 World
</div>

大概是这么一个过程,本质就是深度优先遍历一棵树,所以【之前 if 中 append 的节点不会重新 append 一遍】

Comment options

谢谢解答,思路很清晰。👍发自我的 iPhone在 2024年10月17日,02:34,XiaoxiaoWu ***@***.***> 写道: appendPlacementNodeIntoContainer 的作用是将完成渲染的 FiberNode 以及其子节点,插入到 DOM 容器中,分两种情况: 如果 finishedWork 是 HostComponent 或 HostText(即 DOM 节点或文本节点),则进行移动或插入操作; 如果 finishedWork 有子节点,且该节点不是 HostComponent 或 HostText 类型,说明它是某种复合组件,通常是自定义的 React 组件或某些内部的特殊节点(例如 Fragment、ContextProvider 等)。这些节点本身不会直接对应 DOM 元素,因此需要递归遍历其子节点,直到找到可以映射到真实 DOM(即 HostComponent 或 HostText)的节点。 举个例子,以下 React 组件结构: function MyComponent() { return ( <div> <span>Hello</span> <>World</> </div> ); } React 组件返回的 JSX 包含一个空的 Fragment(<>World</>)。这个情况下,React Fiber 树中会有一个 Fragment 节点,但它不会直接映射到实际的 DOM 元素。 MyComponent 的 Fiber 树结构会像这样: finishedWork(MyComponent 的 Fiber) child → <div> 的 Fiber(HostComponent) child → <span> 的 Fiber(HostComponent) child → "Hello" 的 Fiber(HostText) sibling → Fragment 的 Fiber child → "World" 的 Fiber(HostText) 遍历过程: MyComponent 的 Fiber: finishedWork.tag 不是 HostComponent 或 HostText,因此不会直接插入到 DOM 中。 递归处理 MyComponent 的 child,即 <div> 的 Fiber。 <div> 的 Fiber: finishedWork.tag 是 HostComponent,表示这是一个真实的 DOM 元素(<div>)。 appendChildToContainer 将 <div> 插入到 hostParent 容器中。 递归处理 <div> 的子节点: 处理 <div> 的 child,即 <span> 的 Fiber。 <span> 是 HostComponent,它被插入到 <div> 中。 递归处理 span 的子节点——文本节点 "Hello"。 处理文本节点 "Hello" 的 Fiber: finishedWork.tag 是 HostText,表示这是一个文本节点,它直接插入到 <span> 中。 处理 Fragment 的 Fiber: Fragment 的 Fiber 节点(<>World</>)不会映射到 DOM,因为它仅用于结构化子节点。 继续递归处理 Fragment 的 child,即文本节点 "World"。 处理文本节点 "World" 的 Fiber: 该 Fiber 是 HostText 类型,表示它是一个文本节点,因此被插入到 <div> 中,作为最后一个子节点。 最终的 DOM 结构如下: <div> <span>Hello</span> World </div> 大概是这么一个过程,本质就是深度优先遍历一棵树,所以【之前 if 中 append 的节点不是会重新 append 一遍】 —Reply to this email directly, view it on GitHub, or unsubscribe.You are receiving this because you commented.Message ID: ***@***.***>
You must be logged in to vote
0 replies
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet

AltStyle によって変換されたページ (->オリジナル) /