代码之家  ›  专栏  ›  技术社区  ›  Lev

反应组件安装正时

  •  3
  • Lev  · 技术社区  · 7 年前

    componentDidMount 独立于同级组件的生命周期方法?从下面的示例来看,似乎只有在装载了所有同级组件之后才调用它。

    假设我们有一个顶层组件,它呈现两个子组件,首先是简单的 render() 另一个相对较慢 渲染() .

    https://codesandbox.io/s/j43klml9py?expanddevtools=1

    TL;DR:


    class SlowComponent extends Component {
      componentDidMount() {
        // perf mark
      }
    
      render() {
        // Simulate slow render
        // Takes 50ms
        return <h3>Slow component</h3>;
      }
    }
    
    class FastComponent extends Component {
      componentDidMount() {
        // perf mark
      }
    
      render() {
        return <h3>Fast component</h3>;
      }
    }
    
    class App extends Component {
      constructor(props) {
        super(props);
    
        // perf mark start
      }
    
      componentDidMount() {
        // perf mark
        // measure all marks and print
      }
    
      render() {
        return (
          <div>
            <FastComponent />
            <SlowComponent />
          </div>
        );
      }
    }
    
    ReactDOM.render(<App />, document.getElementById('root'));
    

    组件安装 时间安排如下:

    1. FastComponent 10毫秒
    2. SlowComponent 50毫秒
    3. App

    组件安装

    1. 快速组件
    2. 慢组件 51毫秒
    3. 52毫秒

    当前的sample和repro代码使用mount回调,但同样适用于 componentDidUpdate .

    完整来源:

    import ReactDOM from "react-dom";
    import React, { Component } from "react";
    
    class SlowComponent extends Component {
      componentDidMount() {
        performance.mark("slow-mounted");
      }
    
      render() {
        // Simulate slow render
        for (var i = 0; i < 10000; i++) {
          for (var j = 0; j < 100; j++) {
            const b = JSON.parse(
              JSON.stringify({
                test: "test" + i,
                test1: i * i * i
              })
            );
          }
        }
        return <h3>Slow component</h3>;
      }
    }
    
    class FastComponent extends Component {
      componentDidMount() {
        performance.mark("fast-mounted");
      }
    
      render() {
        return <h3>Fast component</h3>;
      }
    }
    
    class App extends Component {
      constructor(props) {
        super(props);
    
        performance.mark("init");
      }
    
      componentDidMount() {
        performance.mark("app-mounted");
    
        performance.measure("slow", "init", "slow-mounted");
        performance.measure("fast", "init", "fast-mounted");
        performance.measure("app", "init", "app-mounted");
    
        console.clear();
    
        console.log(
          "slow",
          Math.round(performance.getEntriesByName("slow")[0].duration)
        );
        console.log(
          "fast",
          Math.round(performance.getEntriesByName("fast")[0].duration)
        );
        console.log(
          "app",
          Math.round(performance.getEntriesByName("app")[0].duration)
        );
    
        performance.clearMarks();
        performance.clearMeasures();
      }
    
      render() {
        return (
          <div>
            <h1>Demo</h1>
            <FastComponent />
            <SlowComponent />
          </div>
        );
      }
    }
    
    ReactDOM.render(<App />, document.getElementById("root"));
    
    4 回复  |  直到 7 年前
        1
  •  5
  •   Sotiris Kiritsis    7 年前

    我假设您使用的是最新的React版本(16.5.0)。

    假设两个组件(一个慢组件和一个快组件)包装在父组件中,则执行流如下所示:

    1. 父组件调用其 UNSAFE_componentWillMount
    2. 按照在render方法中定义的顺序迭代所有子级,并调用它们的 不安全的组件将安装 方法
    3. 迭代所有子级并调用它们的 render 方法(在这里您的慢组件渲染方法将启动)
    4. 迭代所有子级并调用它们的 componentDidMount 方法
    5. 父组件调用其 方法

    整个过程是同步进行的。

    回到您的示例,这就是为什么您看到两个组件的时间几乎相同的原因,因为所有组件的工作一完成,所有组件生命周期方法都会被调用。

    “提交”阶段是React应用任何更改的时候,在您的示例中是生命周期方法 组件安装

    componentDidMount
    commitLifeCycles
    commitAllLifeCycles
    callCallback
    invokeGuardedCallbackDev
    invokeGuardedCallback
    commitRoot
    
        2
  •  1
  •   sultan    7 年前

    简单的答案

    componentDidMount 方法在所有渲染完成后。因为在将元素装载到DOM之前,我们需要创建它们。

        3
  •  1
  •   Adeel Imran    7 年前

    现在假设,如果没有I/O,也就是说,在子组件的任何地方都会发生异步事件。

    -- Parent
      -- Child-1
      -- Child-2
    

    执行令

    Parent constructor()
    Child 1 constructor()
    Child 1 render()
    Child 1 componentDidMount()
    Child 2 constructor()
    Child 2 render()
    Child 2 componentDidMount()
    Parent componentDidMount()
    

    根据ReactJS文档,安装触发器的顺序如下

    • 构造函数()
    • 渲染()

    参考react文件中的安装顺序 Mounting React Docs

    Understanding React — Component life-cycle

        4
  •  0
  •   shah chaitanya    7 年前

    是的,ComponentDidMount生命周期方法独立于同级组件。这取决于渲染所需的时间,因为它在渲染完成后调用。但是组件的装载顺序与它们在父组件中的顺序相同。例如-在上面的例子中,第一个快速组件安装在第二个组件上。