react 从入门到实践之 react 的生命周期函数和原理

一、react 的生命周期函数

  1. 组件的生命周期可以帮助我们清楚的剖析一个组件从创建到销毁的全部流程。如果能够做到知其然且知其所以然, 那么在后期多组件、中大型项目开发过程中,就能够很好的把控项目的性能细节。

  2. react 生命周期阶段划分,如下所示:

  • 初始化阶段,在组件初始化阶段会执行,主要有 constructor、componentWillMount、render 和 componentDidMount
  • 更新阶段,propsstate 的改变可能会引起组件的更新,组件重新渲染的过程中会调用以下方法,主要有 componentWillUpdate、render 和 componentDidUpdate
  • 卸载阶段,有 componentWillUnmount
  • 错误处理,有 componentDidCatch
  1. react 组件运作流程,如下所示:
  • 首次初始化渲染: React.render(),如下:
    • 1)constructor,创建对象初始化 state
    • 2)componentWillMount,组件即将被渲染,产生该回调
    • 3)render,组件被渲染,产生该回调
    • 4)componentDidMount,组件渲染完成,产生该回调
  • 组件每次发生更新: state: this.setState({}),如下:
    • 1)componentWillUpdate,即将更新,产生该回调
    • 2)render,重新渲染
    • 3)componentDidUpdate,更新完成,产生该回调
  • 卸载阶段,如下:
    • 1)componentWillUnmount,组件即将被移除,产生该回调
    • 2)移除组件,ReactDOM.unmountComponentAtNode(container)
  1. react 生命周期的执行,代码如下所示:
 <script type="text/babel">
    class Life extends React.Component {
     
      constructor (props) {
     
        super(props)
        console.log('constructor(props)')
      }

      componentWillMount () {
     
        console.log('componentWillMount()')
      }

      render () {
     
        console.log('render()')
        return (
          <div>
            <h2>测试组件的钩子函数</h2>
          </div>
        )
      }

      componentDidMount () {
     
        console.log('componentDidMount()')
      }

      componentWillUpdate () {
     
        console.log('componentWillUpdate()')
      }

      componentDidUpdate () {
     
        console.log('componentDidUpdate()')
      }

      componentWillUnmount () {
     
        console.log('componentWillUnmount()')
      }

      componentDidCatch () {
     
        console.log('componentDidCatch()')
      }
    }

    ReactDOM.render(<Life/>, document.getElementById('app'))
  </script>
  1. react 的生命周期函数的定时器,代码如下所示:
 <script type="text/babel">

    class Life extends React.Component {
     
      constructor (props) {
     
        super(props)
        console.log('constructor(props)')
        this.state = {
     
          age: 1
        }
      }

      componentWillMount () {
     
        console.log('componentWillMount()')
      }

      render () {
     
        console.log('render()')
        return (
          <div>
            <h2>测试组件的钩子函数</h2>
            <p>年龄:{
     this.state.age}</p>
            <button onClick={
     () => ReactDOM.unmountComponentAtNode(document.getElementById('app'))}>组件卸载</button>
          </div>
        )
      }

      componentDidMount () {
     
        console.log('componentDidMount()')
        this.intervalId = setInterval(() => {
     
          this.setState({
     
            age: this.state.age + 1
          })
        }, 1000)
      }

      componentWillUpdate () {
     
        console.log('componentWillUpdate()')
      }

      componentDidUpdate () {
     
        console.log('componentDidUpdate()')
      }

      componentWillUnmount () {
     
        console.log('componentWillUnmount()')
        clearInterval(this.intervalId)
      }

      componentDidCatch () {
     
        console.log('componentDidCatch()')
      }
    }

    ReactDOM.render(<Life/>, document.getElementById('app'))
  </script>

二、react 的生命周期函数详解

  1. constructor(props),如下所示:
  • react 组件的构造函数, 在挂载之前被调用。在实现 React.Component 构造函数时,需要先在添加其他内容前,调用 super(props),用来将父组件传来的 props 绑定到这个类中,使用 this.props 将会得到。
  • constructor 中应当做些初始化的行为,如:初始化 state,将事件处理函数绑定到类实例上,但不要使用 setState()。如果没有必要初始化state 或绑定方法,则不需要构造 constructor,或者把这个组件换成纯函数写法。
  • 可以利用 props 初始化 state,在之后修改 state 不会对 props 造成任何修改,但仍然建议提升状态到父组件中,或使用 redux 统一进行状态管理。
  • 官方建议不要在constructor引入任何具有副作用和订阅功能的代码,这些应当在 componentDidMount()中写入。
  1. getDerivedStateFromProps(nextProps, prevState),如下所示:
  • getDerivedStateFromProps在组件实例化后,或者接受新的props后被调用。他返回一个对象来更新状态,或者返回null表示新的props不需要任何state的更新。
  • 如果是由于父组件的props更改,所带来的重新渲染,也会触发此方法。调用steState()不会触发getDerivedStateFromProps()
  1. componentWillMount() / UNSAFE_componentWillMount(),如下所示:
  • componentWillMount()将在 react 未来版本中被弃用; UNSAFE_componentWillMount()在组件挂载前被调用,在这个方法中调用 setState()不会起作用,因为它在 render() 前被调用。
  • 为了避免副作用和其他的订阅,官方建议使用 componentDidMount() 代替。这个方法也是用于在服务器渲染上的唯一方法。
  1. render(),如下所示:
  • render()方法是必需的。当被调用时,将计算 this.propsthis.state,并返回以下一种类型
  • React元素, 通过 jsx 创建,既可以是 dom 元素,也可以是用户自定义的组件。
  • 字符串或数字, 他们将会以文本节点形式渲染到 dom 中。
  • Portals, react 16 版本中提出的新的解决方案,可以使组件脱离父组件层级直接挂载在 DOM 树的任何位置。
  • null, 什么也不渲染。
  • 布尔值, 也是什么都不渲染,通常后跟组件进行判断。
  • 当返回 null,false,ReactDOM.findDOMNode(this)将会返回 null,什么都不会渲染。
  • 注意: render() 方法必须是一个纯函数,不能在里面改变 state,也不能直接和浏览器进行交互,而是应该将事件放在其他生命周期函数中。 如果 shouldComponentUpdate() 返回 falserender() 不会被调用。
  1. componentWillReceiveProps(),如下所示:
  • 官方建议使用 getDerivedStateFromProps 函数代替 componentWillReceiveProps()
  • 当组件挂载后,接收到新的 props 后会被调用。如果需要更新 state 来响应 props 的更改,则可以进行 this.propsnextProps 的比较,并在此方法中使用 this.setState()。如果父组件会让这个组件重新渲染,即使 props没有改变,也会调用这个方法。
  • react 不会在组件初始化 props 时调用这个方法, 调用 this.setState 也不会触发。
  1. shouldComponentUpdate(nextProps, nextState),如下所示:
  • 调用 shouldComponentUpdate, 可以让 react知道组件的输出是否受 stateprops的影响。默认每个状态的更改都会重新渲染,大多数情况下应该保持这个默认行为。在渲染新的 propsstate前,shouldComponentUpdate会被调用, 默认为true。这个方法不会在初始化时被调用,也不会在forceUpdate()时被调用。返回false不会阻止子组件在state更改时重新渲染。
  • 如果shouldComponentUpdate()返回falsecomponentwillupdate,render和componentDidUpdate不会被调用。在未来版本,shouldComponentUpdate()将会作为一个提示而不是严格的指令,返回false仍然可能导致组件的重新渲染。官方并不建议在shouldComponentUpdate()中进行深度查询或使用JSON.stringify(),他效率非常低,并且损伤性能。
  1. UNSAFE_componentWillUpdate(nextProps, nextState),如下所示:
  • 在渲染新的stateprops时,UNSAFE_componentWillUpdate会被调用,将此作为在更新发生之前进行准备的机会。这个方法不会在初始化时被调用。不能在这里使用this.setState(),也不能做会触发视图更新的操作。如果需要更新stateprops,调用getDerivedStateFromProps
  1. getSnapshotBeforeUpdate(),如下所示:
  • react render()后的输出被渲染到 DOM 之前被调用。它让组件能够在它们被潜在更改之前捕获当前值(如滚动位置)。这个生命周期返回的任何值都将作为参数传递给 componentDidUpdate()
  1. componentDidUpdate(prevProps, prevState, snapshot),如下所示:
  • 调用 shouldComponentUpdate, 可以让 react 知道组件的输出是否受 stateprops的影响。默认每个状态的更改都会重新渲染,大多数情况下应该保持这个默认行为。在渲染新的propsstate前,shouldComponentUpdate会被调用, 默认为 true。这个方法不会在初始化时被调用,也不会在 forceUpdate() 时被调用。返回 false不会阻止子组件在 state更改时重新渲染。
  • 如果 shouldComponentUpdate()返回falsecomponentwillupdate,render和componentDidUpdate不会被调用。在未来版本,shouldComponentUpdate()将会作为一个提示而不是严格的指令,返回false仍然可能导致组件的重新渲染。官方并不建议在shouldComponentUpdate()中进行深度查询或使用JSON.stringify(),他效率非常低,并且损伤性能。

你可能感兴趣的:(React,react,从入门到实践,生命周期函数和原理)