快来退出咱们吧!

"小和山的菜鸟们",为前端开发者提供技术相干资讯以及系列根底文章。为更好的用户体验,请您移至咱们官网小和山的菜鸟们 ( https://xhs-rookies.com/ ) 进行学习,及时获取最新文章。

"Code tailor" ,如果您对咱们文章感兴趣、或是想提一些倡议,微信关注 “小和山的菜鸟们” 公众号,与咱们取的分割,您也能够在微信上观看咱们的文章。每一个倡议或是同意都是对咱们极大的激励!

前言

这节咱们将介绍 React 中组件的生命周期,以及和生命周期互相关联的申明周期函数。

留神:本文所介绍的生命周期为 React 17.0.1 版本,读者期间兴许会有改变,最终生命周期等办法和过程请以官网为主,react 官网

本文会向你介绍以下内容:

  • 意识生命周期
  • 生命周期解析
  • 罕用生命周期函数
  • 不罕用生命周期

意识生命周期

很多的事物都有从创立到销毁的整个过程,这个过程称之为是生命周期

React 组件也有本人的生命周期,理解组件的生命周期能够让咱们在最合适的中央实现本人想要的性能;

在组件通过不同的生命周期,就会有不同的生命周期函数被触发,让咱们在最合适的中央写入逻辑。

例如:

有一个组件,在生成的时候须要调用网络申请数据,那么就应该在 componentDidMount() 办法中去申请网络。

留神: 咱们谈 React 生命周期时,次要谈的类的生命周期,因为函数式组件是没有生命周期函数的;

生命周期解析

每个类组件都蕴含 “生命周期办法”,你能够重写这些办法,以便于在运行过程中特定的阶段执行这些办法,咱们来学习一下这些的生命周期函数,上面是官网给出的生命周期图谱:

挂载时:

  • 当咱们挂载一个组件时,会先执行 constructor 构造方法来创立组件;
  • 而后会调用 getDerivedStateFromProps,它应返回一个对象来更新 state,如果返回 null 则不更新任何内容。
  • 紧接着调用 render 函数,获取要渲染的 DOM 构造(jsx),并且开始渲染 DOM
  • 当组件挂载胜利(DOM 渲染实现),会执行 componentDidMount 生命周期函数;

更新时:

  • 当咱们通过批改 props,或者调用 setState 批改外部状态,或者间接调用 forceUpdate 时会从新调用 render 函数,进行更新操作;
  • 当组件的 propsstate 发生变化时会触发更新。此时会调用 getDerivedStateFromProps,它应返回一个对象来更新 state,如果返回 null 则不更新任何内容。
  • 而后会调用 shouldComponentUpdate,并依据此函数的返回值,判断 React 组件的输入是否受以后 state 或 props 更改的影响。
  • 紧接着会调用 render 函数,随即调用 getSnapshotBeforeUpdate ,进行更新操作
  • 当更新实现时,会回调 componentDidUpdate 生命周期函数;

卸载时:

  • 当咱们的组件不再应用,会被从 DOM 中移除掉(卸载);
  • 这个时候会回调 componentWillUnmount 生命周期函数;

罕用生命周期函数

render

render()

render() 办法是 class 组件中惟一必须实现的办法。

render 被调用时,它会查看 this.propsthis.state 的变动并返回以下类型之一:

  • React 元素。通常通过 JSX 创立。
  • 数组或 fragments。 使得 render 办法能够返回多个元素。
  • Portals。能够渲染子节点到不同的 DOM 子树中。
  • 字符串或数值类型。它们在 DOM 中会被渲染为文本节点
  • 布尔类型或 null。什么都不渲染。

render() 函数应该为纯函数,这意味着在不批改组件 state 的状况下,每次调用时都返回雷同的后果,并且它不会间接与浏览器交互。

如需与浏览器进行交互,请在 componentDidMount() 或其余生命周期办法中执行你的操作。放弃 render() 为纯函数,能够使组件更容易思考。

留神: 如果 shouldComponentUpdate() 返回 false,则不会调用 render()

constructor

constructor(props)

如果不初始化 state 或不进行办法绑定,则不须要为 React 组件实现构造函数。

constructor 中通常只做两件事件:

  • 通过给 this.state 赋值对象来初始化外部的 state
  • 为事件绑定实例(this);
constructor(props) {  super(props);  // 不要在这里调用 this.setState()  this.state = { counter: 0 };  this.handleClick = this.handleClick.bind(this);}

只能在构造函数中间接为 this.state 赋值。如需在其余办法中赋值,你应应用 this.setState() 代替。

留神: 防止将 props 的值赋值给 state!这是一个常见的谬误

componentDidMount

componentDidMount()

componentDidMount() 会在组件挂载后(插入 DOM 树中)立刻调用。

componentDidMount 中通常进行哪里操作呢?

  • 依赖于 DOM 的操作能够在这里进行;
  • 在此处发送网络申请就最好的中央;(官网倡议)
  • 能够在此处增加一些订阅(会在 componentWillUnmount 勾销订阅);

componentDidUpdate

componentDidUpdate(prevProps, prevState, snapshot)

componentDidUpdate() 会在更新后会被立刻调用,首次渲染不会执行此办法。

  • 当组件更新后,能够在此处对 DOM 进行操作;
  • 如果你对更新前后的 props 进行了比拟,也能够抉择在此处进行网络申请;(例如,当 props 未发生变化时,则不会执行网络申请)。
componentDidUpdate(prevProps) {  // 典型用法(不要遗记比拟 props):  if (this.props.userID !== prevProps.userID) {    this.fetchData(this.props.userID);  }}

你也能够在 componentDidUpdate()间接调用 setState(),但请留神它必须被包裹在一个条件语句里,正如上述的例子那样进行解决,否则会导致死循环。

留神: 如果 shouldComponentUpdate() 返回值为 false,则不会调用 componentDidUpdate()

componentWillUnmount

componentWillUnmount()

componentWillUnmount() 会在组件卸载及销毁之前间接调用。

  • 在此办法中执行必要的清理操作,例如,革除 timer,勾销网络申请或革除在 componentDidMount() 中创立的订阅等;
  • componentWillUnmount()不应调用 setState(),因为该组件将永远不会从新渲染。组件实例卸载后,将永远不会再挂载它。

代码验证上述罕用的生命周期函数:

import React, { Component } from 'react'class HYTestCpn extends Component {  render() {    return <h2>HYTestCpn</h2>  }  componentWillUnmount() {    console.log('HYTestCpn componentWillUnmount')  }}export default class App extends Component {  constructor(props) {    super(props)    this.state = {      counter: 0,    }    console.log('调用constructor办法')  }  render() {    console.log('调用render办法')    return (      <div>        <h2>以后计数: {this.state.counter}</h2>        {this.state.counter <= 5 && <HYTestCpn />}        <button onClick={(e) => this.increment()}>+1</button>      </div>    )  }  increment() {    this.setState({      counter: this.state.counter + 1,    })  }  componentDidMount() {    console.log('调用componentDidMount办法')  }  componentDidUpdate() {    console.log('调用componentDidUpdate办法')  }  componentWillUnmount() {    console.log('调用componentWillUnmount办法')  }}

不罕用生命周期

除了下面介绍的罕用生命周期函数之外,还有一些不罕用的生命周期函数:

shouldComponentUpdate

shouldComponentUpdate(nextProps, nextState)

propsstate 发生变化时,shouldComponentUpdate() 会在渲染执行之前被调用。返回值默认为 true。首次渲染或应用 forceUpdate() 时不会调用该办法。

  • 依据 shouldComponentUpdate() 的返回值,判断 React 组件的输入是否受以后 stateprops 更改的影响。
  • 默认行为是 state 每次发生变化组件都会从新渲染。大部分状况下,你应该遵循默认行为。
  • 此办法仅作为性能优化的形式而存在。不要希图依附此办法来“阻止”渲染,因为这可能会产生 bug

咱们首先应该思考应用内置的 PureComponent组件,而不是手动编写,PureComponent 会对 propsstate 进行浅层比拟,并缩小了跳过必要更新的可能性。

如果须要手动编写,能够将 this.propsnextProps 以及 this.statenextState 进行比拟,并返回 false 以告知 React 能够跳过更新。请留神,返回 false 并不会阻止子组件在 state 更改时从新渲染。

getDerivedStateFromProps

static getDerivedStateFromProps(props, state)

getDerivedStateFromProps 会在调用 render 办法之前调用,并且在初始挂载及后续更新时都会被调用。

  • 它应返回一个对象来更新 state,如果返回 null 则不更新任何内容。
  • getDerivedStateFromProps 的存在只有一个目标:让组件在 props 变动时更新 state,即 state 的值在任何时候都取决于 props
  • 此办法无权拜访组件实例。
留神: 不论起因是什么,都会在每次渲染前触发此办法。

getSnapshotBeforeUpdate

getSnapshotBeforeUpdate(prevProps, prevState)

React 更新 DOM 之前回调的一个函数,能够获取 DOM 更新前的一些信息(比如说滚动地位);

  • 此生命周期的任何返回值将作为参数传递给 componentDidUpdate()
  • 此用法并不常见,但它可能呈现在 UI 解决中,如须要以非凡形式解决滚动地位的聊天线程等。
  • 应返回 snapshot 的值(或 null)。

另外,React 中还提供了一些过期的生命周期函数,这些函数曾经不举荐应用。

更具体的生命周期相干的内容,能够参考React 官网