前端技术专家面试-React

331 阅读2分钟

一、Filber

1. Filber简化数据结构

// 简化
class FiberNode {
  constructor(component, child = null, sibling = null) {
    this.component = component;
    this.child     = child;   // FiberNode
    this.sibling   = sibling; // FiberNode
    this.return    = null;    // FiberNode 指向父节点
  }
}

2. 页面布局

+------------------+
|       App        |
+------------------+
|      Header      |
+------------------+
|     |        |   |
|  L  | Content|  R|
|     |        |   |
+------------------+
|      Footer      |
+------------------+

3. JSX & 树形表示

// 1. JSX
<App>
    <Header></Header>
    <MainContent>
        <LeftSidebar></LeftSidebar>
        <Content></Content>
        <RightSidebar></RightSidebar>
    </MainContent>
    <Footer></Footer>
</App>


// 2. 图示 
       App
        |
        |
   +----+----+----+----+
   |         |         |
Header   MainContent  Footer
              |
      +-------+--------+
      |       |        |
LeftSidebar   |     RightSidebar
           Content


// 3. JSON表示
{
   "type": "App",
   "children": [
       { "type": "App", }
       { "type": "MainContent", "children": [
                               { "type": "LeftSidebar", }
                               { "type": "Content", }               
                               { "type": "RightSidebar", }]}
       { "type": "Footer", }
   ]
}

4. Filber表示

// 1. 向下便是child
// 2. 向右表示sibling
  App
   | 
   | child
   ↓    sibling             sibling
Header ------→ MainContent -----→ Footer
                     | 
                     | child
                     ↓      sibling        sibling
                LeftSidebar -----→ Content -----→RightSidebar

 // 3. JSON表示
 {
  "type": "App",
  "child": {
    "type": "Header",
    "sibling": {
      "type": "MainContent",
      "child": {
        "type": "LeftSidebar",
        "sibling": {
          "type": "Content",
          "sibling": {
            "type": "RightSidebar"
          }
        }
      },
      "sibling": { "type": "Footer" }
    }
  }
}

5. 深度优先遍历

  • 使用深度优先搜索(DFS)算法遍历 Fiber 树。这意味着它会先完全遍历一个分支,然后再回溯到其他分支。
  • 遍历顺序通常如下:有child先访问child,没有child访问sibling,没有sibling访问return,直到根节点。
    • child:首先访问当前节点的第一个子节点
    • sibling:如果没有子节点,则访问兄弟节点
    • return:如果没有兄弟节点,则返回到父节点
App -> Header -> MainContent -> LeftSidebar -> Content -> RightSidebar ->
Footer -> Return到根节点结束

6. why: 在处理大量节点的时候,链表比数组更快。

  1. 操作效率:
    1. 深度优先遍历简单,
    2. 同一个父节点的子节点进行添加和删除简单。调和过程中最重要的就是同一个父节点的子节点进行比较。
    3. 添加或删除节点在链表结构中更为简单和高效(操作数组没有修改指针块)。
    // 递归
    function dfs(filber) {
        process(filber); // 或者其他处理逻辑
        if (filber.child)  dfs(filber.child);
        if (filber.sibling) dfs(filber.sibling);
    }
    // while遍历,太方便了,while的效率高于递归,特别是数有很大的深度的场景
    function dfs(filber) {
        let current = filber;
        while (current) {
            process(current);
            if (current.child) {
                current = current.child;
                continue;
            }
            if (current.sibling) {
                current = current.sibling;
                continue;
            } 
        }
    }
    
  2. 增量渲染:filber只需要记录current;数组结构则需要额外的机制来记录遍历状态。
  3. 优先级调度:和数组的形式比,差距在大数据量的时候。
    • Fiber结构允许React更容易地实现优先级调度,可以更灵活地决定遍历和处理的顺序。
    • 链表结构使得跳过或推迟某些分支的处理变得更加简单。
  4. 双缓冲技术:
    • Fiber使用双缓冲技术来构建和比较树。链表结构使得在两棵树之间建立和维护联系更加直观和高效。
  5. 代码复用:
    • 链表结构允许更多的代码复用,因为许多操作(如插入、删除、遍历)可以用相同的模式处理 child 和 sibling。

react

虚拟DOM

渲染过程

参考

blog.csdn.net/qq_16546829…