React面试葵花宝典之二

36.Fiber的更新机制

React Fiber 更新机制详解

React Fiber 是 React 16 引入的核心架构重构,旨在解决可中断渲染优先级调度 问题,提升复杂应用的流畅性。其核心思想是将渲染过程拆分为可控制的工作单元,实现更细粒度的任务管理。以下是其核心机制:


一、Fiber 架构的设计目标
  1. 可中断与恢复:允许渲染过程被高优先级任务(如用户输入)打断,后续恢复。
  2. 增量渲染:将渲染任务拆分为多个小任务(时间分片),避免阻塞主线程。
  3. 优先级调度:根据任务类型(如动画、数据加载)分配不同优先级。
  4. 并发模式支持:为 Suspense、Transition 等特性提供底层支持。

二、Fiber 节点:工作单元的基础

每个 Fiber 节点对应一个组件或 DOM 节点,构成链表树结构,包含以下关键信息:

  • 组件类型:函数/类组件、HTML 标签等。

  • 状态与 Propsstatepropscontext

  • 副作用标记 :增/删/更新 DOM、调用生命周期等(通过 flags 字段标识)。

  • 链表指针

    • child:指向第一个子节点。
    • sibling:指向下一个兄弟节点。
    • return:指向父节点。
  • 优先级lane 模型标记任务优先级(如 SyncLane、InputContinuousLane)。


三、更新流程:从触发到提交
1. 触发更新
  • 来源setStateuseState、父组件重渲染、Context 变更等。
  • 创建更新对象:包含新状态、优先级等信息,添加到 Fiber 的更新队列。
2. 调度阶段(Scheduler)
  • 任务分片:将整个渲染流程拆分为多个 Fiber 节点的处理单元。
  • 优先级排序 :使用 lane 模型分配优先级,高优先级任务可抢占低优先级。
  • 时间切片 :通过 requestIdleCallbackMessageChannel 在浏览器空闲时段执行任务。
3. 协调阶段(Reconciler)
  • 构建 WorkInProgress 树:在内存中生成新 Fiber 树(双缓存机制)。
  • Diff 算法 :对比新旧 Fiber 节点,标记变更(如 PlacementUpdateDeletion)。
  • 生命周期触发 :执行函数组件的渲染、类组件的 render 方法。
4. 提交阶段(Commit)
  • 同步执行:不可中断,一次性将变更应用到 DOM。

  • 副作用处理

    • DOM 操作:增删改节点。
    • 生命周期 :类组件的 componentDidMount/Update
    • HooksuseLayoutEffect 回调。
  • 切换当前树 :将 WorkInProgress 树标记为 current 树。


四、优先级调度与中断机制
  • Lane 模型 :用二进制位表示优先级(如 0b00010b0010 可合并为 0b0011)。
  • 高优先级抢占:用户交互触发的更新(如按钮点击)可中断正在进行的低优先级渲染(如大数据列表渲染)。
  • 饥饿问题处理:长时间未执行的低优先级任务会被提升优先级。

示例场景

用户输入搜索关键词时,输入框的即时响应(高优先级)会中断后台数据渲染(低优先级)。


五、双缓存技术
  • Current 树:当前屏幕上显示的 Fiber 树。
  • WorkInProgress 树:正在构建的新树,完成后替换 Current 树。
  • 优势:减少渲染过程中的页面闪烁,确保原子性更新。

六、并发模式下的更新
  • 过渡更新(Transition) :通过 startTransition 标记非紧急更新(如页面切换),可被用户交互打断。

    复制代码
    const [isPending, startTransition] = useTransition();
    startTransition(() => {
      setPage(newPage); // 低优先级更新
    });
  • Suspense:配合懒加载组件,在数据加载时显示 fallback UI。


七、性能优化启示
  1. 减少渲染粒度 :使用 React.memouseMemo 避免无效渲染。
  2. 合理分配优先级 :紧急操作使用高优先级,长任务用 startTransition 包裹。
  3. 优化 Fiber 树深度:扁平化组件结构,减少协调时间。

总结

React Fiber 通过可中断的异步渲染优先级调度,彻底改变了 React 的渲染机制。其核心价值在于:

  • 更流畅的交互:高优先级任务快速响应,避免界面卡顿。
  • 更高效的渲染:增量更新减少主线程阻塞。
  • 面向未来的扩展:为并发特性(如 Suspense、Server Components)奠定基础。

37.React18有哪些更新

React 18 主要更新详解

React 18 引入了多项重要改进和新特性,旨在提升性能、开发体验及扩展能力。以下是其核心更新内容:


1. 并发渲染(Concurrent Rendering)
  • 核心机制:通过可中断的渲染过程,实现任务优先级调度与时间分片。

    • 并发模式(Concurrent Mode) :现称为"并发特性",无需全局开启,按需使用。
    • API支持startTransitionuseDeferredValue 等。
  • 优势

    • 高优先级任务(如用户输入)可中断低优先级渲染,提升交互流畅度。
    • 支持复杂场景下的无缝过渡(如页面切换、数据加载)。

示例

复制代码
import { startTransition } from 'react';

// 标记非紧急更新
startTransition(() => {
  setSearchQuery(input); // 延迟渲染搜索结果,保持输入响应
});

2. 自动批处理(Automatic Batching)
  • 改进点:在更多场景下合并状态更新,减少渲染次数。

    • React 17及之前:仅在事件处理函数中批处理。
    • React 18:扩展至Promise、setTimeout等异步操作。
  • 效果:降低不必要的重渲染,优化性能。

示例

复制代码
// React 18:两次setState合并为一次渲染
setTimeout(() => {
  setCount(1);
  setFlag(true);
}, 1000);

3. 新的根API(createRoot)
  • 替换旧API :使用 createRoot 替代 ReactDOM.render,启用并发特性。

  • 用法

    复制代码
    import { createRoot } from 'react-dom/client';
    
    const root = createRoot(document.getElementById('root'));
    root.render(<App />);

4. Suspense 增强
  • 服务端渲染(SSR)支持

    • 流式HTML传输:逐步发送HTML,加速首屏加载。
    • 选择性Hydration:优先为交互部分注水,提升可交互时间(TTI)。
  • 客户端扩展:支持在更多场景包裹异步组件或数据加载。

示例

复制代码
<Suspense fallback={<Loading />}>
  <AsyncComponent />
</Suspense>

5. 新Hooks API
  • useId:生成唯一ID,解决SSR与客户端ID不一致问题。

    复制代码
    const id = useId(); // 生成如 ":r1:"
  • useSyncExternalStore:简化外部状态库(如Redux)集成。

    复制代码
    const state = useSyncExternalStore(store.subscribe, store.getState);
  • useInsertionEffect:适用于CSS-in-JS库动态插入样式。

    复制代码
    useInsertionEffect(() => {
      const style = document.createElement('style');
      style.innerHTML = `.css { color: red }`;
      document.head.appendChild(style);
    });

6. 过渡API(Transitions)
  • 区分紧急/非紧急更新 :通过 startTransition 延迟非关键渲染。

  • UI反馈useTransition 提供 isPending 状态,显示加载指示。

    复制代码
    const [isPending, startTransition] = useTransition();
    
    startTransition(() => {
      setTab(newTab); // 非紧急导航
    });
    
    return isPending ? <Spinner /> : <Content />;

7. 严格模式增强
  • 开发环境行为

    • 双调用Effects:模拟组件卸载/挂载,暴露副作用问题。
    • 组件重复挂载:检查是否正确处理清理逻辑(如定时器、订阅)。

8. 服务端组件(实验性)
  • 核心能力

    • 服务端渲染组件:在服务端执行,减少客户端代码体积。
    • 无缝数据获取:直接访问后端API,传递序列化数据至客户端。
  • 使用场景:静态内容、SEO优化、性能敏感页面。

示例

复制代码
// ServerComponent.server.js
export default function ServerComponent() {
  const data = fetchData(); // 服务端执行
  return <div>{data}</div>;
}

9. 其他改进
  • 性能优化:减少内存占用,提升大型应用渲染效率。
  • TypeScript支持:更严格的类型推断,减少显式类型声明。
  • 开发者工具:增强并发模式调试支持,可视化渲染优先级。

升级指南

  1. 兼容性:React 18 保持向后兼容,逐步采用新特性。

  2. 迁移步骤

    • 使用 createRoot 替换 ReactDOM.render
    • 按需引入并发API(如 startTransition)。
    • 测试严格模式下的副作用处理。

总结

React 18 通过并发渲染、自动批处理、Suspense增强等特性,显著提升了应用性能与用户体验。开发者可通过渐进式升级,利用新API优化交互流畅度与渲染效率,同时为未来特性(如服务端组件)奠定基础。

38.Rect19有哪些新特性

具体详见官网:

中文:React 19 新特性

英文:React 19 新特性

核心新特性

1. Actions

解决问题:简化数据变更和状态更新流程

  • 以前需要手动处理待定状态、错误、乐观更新和顺序请求
  • 需要维护多个状态变量(isPending, error 等)

新特性

typescript 复制代码
function UpdateName() {
  const [state, submitAction, isPending] = useActionState(
    async (prevState, formData) => {
      const error = await updateName(formData.get("name"));
      if (error) return error;
      redirect("/path");
      return null;
    },
    null
  );

  return (
    <form action={submitAction}>
      <input name="name" />
      <button disabled={isPending}>Update</button>
      {state?.error && <p>{state.error}</p>}
    </form>
  );
}

主要改进

  • 自动处理待定状态
  • 内置错误处理
  • 支持乐观更新
  • 简化表单处理

2. useFormStatus

解决问题:简化表单组件状态访问

  • 避免通过 props 传递表单状态
  • 提供统一的表单状态访问方式
typescript 复制代码
function SubmitButton() {
  const { pending, data, method } = useFormStatus();
  return (
    <button disabled={pending}>
      {pending ? 'Submitting...' : 'Submit'}
    </button>
  );
}

3. useOptimistic

解决问题:提供更好的用户体验

  • 立即显示操作结果
  • 处理异步操作的状态更新
typescript 复制代码
function LikeButton({ id }) {
  const [likes, setLikes] = useState(0);
  const [optimisticLikes, addOptimisticLike] = useOptimistic(
    likes,
    (state, increment) => state + increment
  );

  async function handleLike() {
    addOptimisticLike(1); // 立即更新 UI
    await updateLikes(id); // 后台进行实际更新
  }
}

4. use() Hook

解决问题:统一资源使用方式

  • 简化 Promise 和 Context 的使用
  • 支持条件性使用
  • 提供更好的类型推断
typescript 复制代码
function Comments({ commentsPromise }) {
  const comments = use(commentsPromise); // 自动处理 Suspense
  return comments.map(comment => <p>{comment}</p>);
}

架构改进

1. Document 流式渲染

解决问题:改善首次加载体验

  • 支持 HTML 流式传输
  • 优化资源加载顺序
typescript 复制代码
function AsyncPage() {
  return (
    <Document>
      <Suspense fallback={<Loading />}>
        <AsyncContent />
      </Suspense>
    </Document>
  );
}

2. 资源处理优化

样式表支持

解决问题:简化样式管理

  • 自动处理样式表加载顺序
  • 支持组件级样式声明
typescript 复制代码
function Component() {
  return (
    <>
      <link rel="stylesheet" href="styles.css" precedence="default" />
      <div className="styled-content">...</div>
    </>
  );
}
异步脚本支持

解决问题:优化脚本加载

  • 自动处理脚本去重
  • 优化加载优先级
typescript 复制代码
function MyComponent() {
  return (
    <div>
      <script async={true} src="widget.js" />
      <div>Widget Content</div>
    </div>
  );
}

开发体验改进

1. 错误处理增强

解决问题:提供更清晰的错误信息

  • 消除重复错误日志
  • 提供更详细的错误上下文
typescript 复制代码
createRoot(container, {
  onCaughtError: (error) => {
    // 错误边界捕获的错误
  },
  onUncaughtError: (error) => {
    // 未被捕获的错误
  },
  onRecoverableError: (error) => {
    // 可恢复的错误
  }
});

2. 自定义元素支持

解决问题:改善与 Web Components 的集成

  • 完整支持自定义元素
  • 正确处理属性和属性传递

最佳实践建议

  1. 渐进式采用

    • 优先使用新的表单处理方式
    • 在关键交互中使用乐观更新
    • 利用新的资源加载优化
  2. 性能优化

    • 使用流式渲染改善加载体验
    • 合理使用资源预加载
    • 优化并发更新
  3. 错误处理

    • 使用新的错误边界
    • 实现适当的降级策略
    • 监控错误模式

服务器组件

1. 服务器组件基础

解决问题:优化应用性能和开发体验

  • 减少客户端 bundle 大小
  • 直接访问后端资源
  • 改善数据获取模式
typescript 复制代码
// 服务器组件
async function Notes() {
  // 直接访问数据库,无需 API 层
  const notes = await db.notes.getAll();
  
  return (
    <div>
      {notes.map(note => (
        <Expandable key={note.id}>
          <p>{note.content}</p>
        </Expandable>
      ))}
    </div>
  );
}

2. 服务器组件与客户端组件集成

解决问题:平滑处理服务器和客户端组件交互

  • 支持渐进式增强
  • 保持交互性
  • 优化数据流
typescript 复制代码
// 服务器组件
import Expandable from './Expandable';  // 客户端组件

async function NotesContainer() {
  const notes = await db.notes.getAll();
  
  return (
    <div>
      {/* 服务器组件可以渲染客户端组件 */}
      <Expandable>
        <NotesList notes={notes} />
      </Expandable>
    </div>
  );
}

// 客户端组件
'use client'
function Expandable({ children }) {
  const [expanded, setExpanded] = useState(false);
  
  return (
    <div>
      <button onClick={() => setExpanded(!expanded)}>
        {expanded ? 'Collapse' : 'Expand'}
      </button>
      {expanded && children}
    </div>
  );
}

3. 异步组件

解决问题:简化异步数据处理

  • 支持 async/await 语法
  • 自动处理 Suspense 集成
  • 优化加载状态
typescript 复制代码
// 服务器组件中的异步数据获取
async function Page({ id }) {
  const note = await db.notes.get(id);
  // 开始获取评论但不等待
  const commentsPromise = db.comments.get(id);
  
  return (
    <div>
      <h1>{note.title}</h1>
      <Suspense fallback={<Loading />}>
        <Comments commentsPromise={commentsPromise} />
      </Suspense>
    </div>
  );
}

Refs 作为 Props

1. 将 ref 作为 prop

从 React 19 开始,你现在可以在函数组件中将 ref 作为 prop 进行访问:

typescript 复制代码
function MyInput({placeholder, ref}) {
  return <input placeholder={placeholder} ref={ref} />
}

//...
<MyInput ref={ref} />

新的函数组件将不再需要 forwardRef,我们将发布一个 codemod 来自动更新你的组件以使用新的 ref prop。在未来的版本中,我们将弃用并移除 forwardRef。

2. Ref 稳定性改进

解决问题:优化 ref 更新和同步

  • 更可预测的 ref 更新时机
  • 更好的并发模式支持
  • 改进的性能特性
typescript 复制代码
function AutoFocusInput() {
  const inputRef = useRef<HTMLInputElement>(null);
  
  // ref 回调模式的改进
  const setRef = useCallback((element: HTMLInputElement | null) => {
    if (element) {
      element.focus();
    }
  }, []);
  
  return <input ref={setRef} />;
}

服务器组件最佳实践

  1. 数据获取策略

    • 在服务器组件中直接访问数据源
    • 使用流式传输处理大量数据
    • 实现适当的缓存策略
  2. 组件分割

    • 将有状态逻辑的组件标记为客户端组件
    • 保持服务器组件纯粹
    • 优化组件边界
  3. 性能优化

    • 使用服务器组件减少客户端 bundle
    • 实现渐进式加载
    • 优化数据预取
typescript 复制代码
// 示例:优化的服务器组件结构
async function BlogPost({ id }) {
  const post = await db.posts.get(id);
  const authorPromise = db.authors.get(post.authorId);
  const commentsPromise = db.comments.get(id);
  
  return (
    <article>
      <h1>{post.title}</h1>
      <Suspense fallback={<AuthorSkeleton />}>
        <Author authorPromise={authorPromise} />
      </Suspense>
      <Content>{post.content}</Content>
      <Suspense fallback={<CommentsSkeleton />}>
        <Comments commentsPromise={commentsPromise} />
      </Suspense>
    </article>
  );
}

注意事项

  1. 服务器组件限制

    • 不能使用浏览器 API
    • 不能使用状态和生命周期
    • 需要正确处理数据获取错误
  2. Ref 使用考虑

    • 注意 ref 的生命周期
    • 合理处理 ref 清理
    • 避免过度依赖 ref
  3. 性能注意事项

    • 平衡服务器和客户端渲染
    • 合理使用 Suspense 边界
    • 优化数据预加载策略
      详细请看链接

39.React为什么不直接使用this.state改变数据

在 React 中,不能直接通过 this.state 来改变数据 ,而必须使用 this.setState() 来更新状态。这背后有几个关键的原因,主要是为了保证 组件的可预测性、性能优化避免直接修改状态 所带来的潜在问题。接下来,我将详细解释这些原因。

1. 不可变数据和状态管理原则

React 提倡 不可变数据 (immutable data)原则,即状态对象一旦创建,它的值就不应该直接修改。直接修改 this.state 会导致组件行为变得难以预测,难以追踪和调试。通过 this.setState(),React 可以保证每次状态更新时,状态对象都是全新的对象,而不是直接修改原有对象。

为什么要避免直接修改 this.state

  • 直接修改状态会破坏数据的不可变性,使得 React 无法检测到变化。
  • 状态不再是新的引用,这使得 React 无法有效地进行比较,进而影响渲染效率。

举个例子,如果直接修改 this.state

复制代码
this.state.someValue = newValue;  // 不推荐

这样 React 就不会知道状态发生了变化,因此不会触发重新渲染,也就无法同步 UI 和状态。

而通过 this.setState()

复制代码
this.setState({ someValue: newValue });  // 推荐

this.setState() 会创建一个新的状态对象,确保 React 能检测到状态变化,并触发 UI 更新。


2. 异步更新与批量更新

this.setState() 的更新是异步的,而直接修改 this.state 是同步的。React 内部有一种机制,用来批量更新状态,以减少不必要的重新渲染。这种机制不仅提高了性能,还避免了多次渲染的重复计算。

例如,假设你直接修改了 this.state,并且立即访问了 this.state 来获取新值。由于 React 的 setState() 是异步的,直接修改 this.state 可能会导致你获取到的状态值不是更新后的值。

复制代码
this.setState({ count: this.state.count + 1 });
console.log(this.state.count); // 可能不会立即反映出最新的状态

React 会将多个 setState() 调用合并到一个批量更新中,以减少不必要的渲染和性能开销。通过使用 this.setState(),React 可以处理这些合并和异步更新的操作。


3. 性能优化

this.setState() 触发的更新过程与直接修改 this.state 的过程有所不同。当调用 setState() 时,React 会合并当前的状态和新的状态,只有发生了变化的部分会被更新。这对于性能优化至关重要。

如果你直接修改 this.state,React 就无法知道哪些部分发生了变化,也就无法进行智能的 diff 和批量更新。例如:

复制代码
this.state.count = 10;  // 直接修改
this.setState({ count: 10 });  // 通过 setState 更新

setState() 中,React 会比较前后的状态,判断是否需要重新渲染组件,而直接修改 this.state 则无法触发这种比较。


4. 组件的生命周期和渲染

this.setState() 触发状态更新时,React 会在合适的生命周期方法中触发组件的重新渲染。例如,在状态更新时,shouldComponentUpdatecomponentDidUpdate 等生命周期方法会被调用,以便开发者可以在状态变化时执行一些操作。如果直接修改 this.state,React 不会知道组件状态发生变化,进而不会触发这些生命周期方法。

这会导致一些问题,比如无法对比新旧状态、无法做条件渲染等操作。


5. React 状态更新的队列机制

React 通过维护一个更新队列来优化状态的更新和渲染。当你调用 this.setState() 时,React 会把状态更新请求放入一个队列,批量处理这些更新。在队列中的多个状态更新可以合并,这避免了不必要的重新渲染,提高了性能。

直接修改 this.state 不会加入更新队列,React 不会触发它的重新渲染机制,因此无法享受 React 的批量更新和性能优化。


6. 追踪组件的变化

React 使用 this.setState() 来管理组件状态,并且通过对比旧的虚拟 DOM 和新的虚拟 DOM,来决定哪些部分需要重新渲染。这个过程需要 React 在底层追踪和比较状态,而直接修改 this.state 会使得这个追踪变得困难,影响性能优化。

通过 this.setState(),React 能够确保组件状态的变化得到跟踪,并且在状态变化时触发重新渲染,确保 UI 始终与状态一致。


7. React 16+ 的 Fiber 架构

在 React 16 及更高版本中,React 引入了 Fiber 架构 ,这使得 React 的渲染变得更加灵活和高效。通过 this.setState(),React 能够控制每一次渲染的优先级,并且通过增量更新来保持 UI 响应性。如果你直接修改 this.state,这种增量更新机制就无法发挥作用。


总结:

  • 数据不可变性this.setState() 遵循不可变数据的原则,避免直接修改原有状态。
  • 异步和批量更新this.setState() 支持异步更新,React 可以批量处理多个状态更新,提升性能。
  • 生命周期管理 :通过 setState,React 能够触发生命周期钩子,确保组件正确更新。
  • 性能优化this.setState() 可以通过智能的差异化更新减少不必要的 DOM 操作,而直接修改 this.state 会跳过这一过程。

因此,直接修改 this.state 会破坏 React 的更新机制,导致状态和 UI 不一致,影响性能和可维护性。React 的设计理念和架构要求我们通过 this.setState() 来更新状态,从而确保更高效和可预测的渲染过程。

40.原来的react虚拟dom树遍历是深度优先遍历还是层序遍历?存储是链表存储还是栈存储,fiber机制下的是如何存储

React 虚拟DOM遍历与存储机制详解


一、传统虚拟DOM(React 15及之前)
  1. 遍历方式深度优先遍历(DFS)

    • 递归处理:从根组件开始,递归处理每个组件及其子组件,直到叶子节点,再回溯处理兄弟节点。

    • 顺序示例

      复制代码
      A → A.child B → B.child C → C.child D → 回溯到 B → B.sibling E → E.child F
  2. 存储结构隐式调用栈

    • 依赖调用栈:递归调用栈隐式管理遍历过程,无显式数据结构存储节点关系。

    • 缺点

      • 不可中断:递归一旦开始必须执行完毕,导致主线程阻塞。
      • 性能瓶颈:深层嵌套组件树易引发栈溢出或卡顿。

二、Fiber架构(React 16+)
  1. 遍历方式可中断的迭代式深度优先遍历

    • 顺序不变:仍按深度优先顺序处理节点(与之前一致)。

    • 实现变化 :从递归改为循环+链表指针手动遍历,支持暂停与恢复。

    • 流程示例

      复制代码
      let fiber = rootFiber;
      while (fiber) {
        process(fiber);      // 处理当前节点
        if (fiber.child) {
          fiber = fiber.child; // 优先处理子节点
          continue;
        }
        while (fiber) {
          completeWork(fiber); // 完成当前节点
          if (fiber.sibling) {
            fiber = fiber.sibling; // 转向兄弟节点
            break;
          }
          fiber = fiber.return;    // 回溯父节点
        }
      }
  2. 存储结构显式链表树

    • Fiber节点结构

      复制代码
      interface Fiber {
        tag: ComponentType;      // 组件类型
        child: Fiber | null;     // 第一个子节点
        sibling: Fiber | null;   // 下一个兄弟节点
        return: Fiber | null;    // 父节点
        alternate: Fiber | null; // 指向另一棵树(双缓存)
        flags: number;           // 副作用标记(增/删/更新)
        lanes: Lanes;            // 优先级
        // ...其他字段(stateNode、props等)
      }
    • 双缓存机制

      • Current树:当前渲染的树(对应屏幕显示内容)。
      • WorkInProgress树:正在构建的新树,完成后替换Current树。
      • 优势:避免渲染中间状态导致的UI闪烁。

三、Fiber架构的核心改进
维度 传统虚拟DOM Fiber架构
遍历控制 递归(不可中断) 迭代(可中断 + 恢复)
数据结构 隐式调用栈 显式链表(child/sibling/return)
任务调度 同步执行 优先级调度 + 时间分片
性能优化 易阻塞主线程 增量渲染,避免卡顿
扩展能力 有限 支持并发模式(Suspense/Transition)

四、Fiber遍历流程示例

假设组件树结构为:

复制代码
A
├─ B
│  ├─ C
│  └─ D
└─ E
   └─ F

遍历顺序

  1. 进入A → 处理A
  2. 进入A.child B → 处理B
  3. 进入B.child C → 处理C
  4. C无子节点 → 完成C,回溯到B
  5. 进入B.sibling D → 处理D
  6. D无子节点 → 完成D,回溯到B → 完成B,回溯到A
  7. 进入A.sibling E → 处理E
  8. 进入E.child F → 处理F
  9. F无子节点 → 完成F,回溯到E → 完成E,回溯到A → 完成A

五、Fiber架构的优势
  1. 可中断渲染:高优先级任务(如用户输入)可打断低优先级渲染。
  2. 增量更新:将渲染任务拆分为多个帧执行,避免主线程阻塞。
  3. 精准副作用提交 :通过 flags 标记变更,一次性提交DOM操作。
  4. 并发模式支持:实现服务端渲染流式输出、Suspense等高级特性。

总结

  • 传统虚拟DOM:深度优先遍历 + 递归调用栈,简单但不可中断。
  • Fiber架构:深度优先遍历 + 显式链表结构,通过迭代实现可中断渲染,结合优先级调度与双缓存机制,为React带来革命性性能提升与扩展能力。
  • 核心价值:将同步渲染转化为异步可调度任务,使复杂应用保持流畅交互。

41.React如何创建工程环境(js,ts),eject的作用是什么?

42.React常见hooks有哪些

相关推荐
gnip1 小时前
链式调用和延迟执行
前端·javascript
SoaringHeart2 小时前
Flutter组件封装:页面点击事件拦截
前端·flutter
杨天天.2 小时前
小程序原生实现音频播放器,下一首上一首切换,拖动进度条等功能
前端·javascript·小程序·音视频
Dragon Wu2 小时前
React state在setInterval里未获取最新值的问题
前端·javascript·react.js·前端框架
Jinuss2 小时前
Vue3源码reactivity响应式篇之watch实现
前端·vue3
YU大宗师2 小时前
React面试题
前端·javascript·react.js
木兮xg2 小时前
react基础篇
前端·react.js·前端框架
ssshooter2 小时前
你知道怎么用 pnpm 临时给某个库打补丁吗?
前端·面试·npm
IT利刃出鞘3 小时前
HTML--最简的二级菜单页面
前端·html
yume_sibai3 小时前
HTML HTML基础(4)
前端·html