React框架生命周期总结

简介: React生命周期中各个生命周期方法的特性和使用技巧。

生命周期(Life Cycle):是指一个对象的生老病死。此处的生命周期指的是在对应的框架中一个组件(对象)或程序从创建到销毁的过程。

React生命周期图

react-life-cycle.png

React生命周期详解

React生命周期大体分为四个周期: 初始化、挂载、更新、卸载。

1.初始化期:

  • getDefautProps (es6: static defaultProps)
  • getInitialState (es6: constructor(props))

2.挂载期:

  • componentWillMount
  • render
  • componentDidMount

3.更新期

  • componentWillReceiveProps
  • shouldComponentUpdate
  • componentWillUpdate
  • render
  • componentDidUpdate

4.卸载

  • componentWillUnmount

    示例演示

初始化和挂载期代码演示:

src/index.js

import ReactDOM from 'react-dom';
import App from './App';

ReactDOM.render(
  <App />,
  document.getElementById('root')
);

src/App.js


class App extends Component {
  static defaultProps = {
    title: (() => {
      console.log(`defaultProps 初始期`)
      return 'app';
    })()
  }

  constructor(props) {
    super(props);
    this.state = {
      name: (() => {
        console.log(`this.state constructor时期`);
        return 'react'
      })()
    }
  }

  componentWillMount() {
    console.log(`componentWillMount 方法`)
  }

  componentDidMount() {
    console.log(`componentDidMount 方法`)
  }

  componentWillReceiveProps() {
    console.log(`componentWillReceiveProps 方法`)
  }

  shouldComponentUpdate() {
    console.log(`shouldComponentUpdate 方法`)
  }

  componentWillUpdate() {
    console.log(`componentWillUpdate 方法`)
  }

  componentDidUpdate() {
    console.log(`componentDidUpdate 方法`)
  }

  componentWillUnmount() {
    console.log(`componentWillUnmount 方法`)
  }

  render() {
    console.log(`render 方法`)
    return <div>{this.props.title} {this.state.name}</div>
  }
}

export default App;

运行结果:

App.js:6 defaultProps 初始期
App.js:15 this.state constructor时期
App.js:22 componentWillMount 方法
App.js:50 render 方法
App.js:26 componentDidMount 方法

更新期代码演示:

更新器分两种情况,一种是自身变化(state),另一种是父组件变化(props)。

自身state变化的情况:

src/App.js


class App extends Component {
  static defaultProps = {
    title: (() => {
      console.log(`defaultProps 初始期`)
      return 'app';
    })()
  }

  constructor(props) {
    super(props);
    this.state = {
      name: (() => {
        console.log(`this.state constructor时期`);
        return 'react'
      })()
    }
  }

  componentWillMount() {
    console.log(`componentWillMount 方法`)
  }

  componentDidMount() {
    console.log(`componentDidMount 方法`)
  }

  componentWillReceiveProps() {
    console.log(`componentWillReceiveProps 方法`)
  }

  shouldComponentUpdate() {
    console.log(`shouldComponentUpdate 方法`)
    return true;
  }

  componentWillUpdate() {
    console.log(`componentWillUpdate 方法`)
  }

  componentDidUpdate() {
    console.log(`componentDidUpdate 方法`)
  }

  componentWillUnmount() {
    console.log(`componentWillUnmount 方法`)
  }

  handleClick() {
    console.log(`点击了【按钮】`);
    this.setState({
      name: 'vue'
    })
  }

  render() {
    console.log(`render 方法`)
    return (
    <div>
      <button onClick={() => this.handleClick()}>按钮</button>
      <br />
      <span>
        {this.props.title} {this.state.name}
      </span>
    </div>
    )
  }
}

export default App;

运行结果:

App.js:6 defaultProps 初始期
App.js:15 this.state constructor时期
App.js:22 componentWillMount 方法
App.js:58 render 方法
App.js:26 componentDidMount 方法
App.js:51 点击了【按钮】
App.js:34 shouldComponentUpdate 方法
App.js:39 componentWillUpdate 方法
App.js:58 render 方法
App.js:43 componentDidUpdate 方法

父组件变化(props)的情况:

src/App.js

import Child from './Child';

class App extends Component {
  static defaultProps = {
    title: (() => {
      console.log(`defaultProps 初始期`)
      return 'app';
    })()
  }

  constructor(props) {
    super(props);
    this.state = {
      name: (() => {
        console.log(`this.state constructor时期`);
        return 'react'
      })()
    }
  }

  componentWillMount() {
    console.log(`componentWillMount 方法`)
  }

  componentDidMount() {
    console.log(`componentDidMount 方法`)
  }

  componentWillReceiveProps() {
    console.log(`componentWillReceiveProps 方法`)
  }

  shouldComponentUpdate() {
    console.log(`shouldComponentUpdate 方法`)
    return true;
  }

  componentWillUpdate() {
    console.log(`componentWillUpdate 方法`)
  }

  componentDidUpdate() {
    console.log(`componentDidUpdate 方法`)
  }

  componentWillUnmount() {
    console.log(`componentWillUnmount 方法`)
  }

  handleClick() {
    console.log(`点击了【按钮】`);
    this.setState({
      name: 'vue'
    })
  }

  render() {
    console.log(`render 方法`)
    return (
    <div>
      <button onClick={() => this.handleClick()}>按钮</button>
      <br />
      <Child title={this.state.name}/>
    </div>
    )
  }
}

export default App;

src/Child.jsx


class Child extends Component {
  
  constructor(props) {
    super(props);
    console.log(`constructor 方法`)
  }

  componentWillMount() {
    console.log(`componentWillMount 方法`)
  }

  componentDidMount() {
    console.log(`componentDidMount 方法`)
  }

  componentWillReceiveProps() {
    console.log(`componentWillReceiveProps 方法`)
  }

  shouldComponentUpdate() {
    console.log(`shouldComponentUpdate 方法`)
    return true;
  }

  componentWillUpdate() {
    console.log(`componentWillUpdate 方法`)
  }

  componentDidUpdate() {
    console.log(`componentDidUpdate 方法`)
  }

  componentWillUnmount() {
    console.log(`componentWillUnmount 方法`)
  }

  render() {
    console.log(`render 方法`)
    return (
    <div>
      {this.props.title}
    </div>
    )
  }
}

export default Child;

运行结果:

App.js:7 defaultProps 初始期
App.js:16 this.state constructor时期
App.js:23 componentWillMount 方法
App.js:59 render 方法
Child.jsx:7 constructor 方法
Child.jsx:11 componentWillMount 方法
Child.jsx:40 render 方法
Child.jsx:15 componentDidMount 方法
App.js:27 componentDidMount 方法
App.js:52 点击了【按钮】
App.js:35 shouldComponentUpdate 方法
App.js:40 componentWillUpdate 方法
App.js:59 render 方法
Child.jsx:19 componentWillReceiveProps 方法
Child.jsx:23 shouldComponentUpdate 方法
Child.jsx:28 componentWillUpdate 方法
Child.jsx:40 render 方法
Child.jsx:32 componentDidUpdate 方法
App.js:44 componentDidUpdate 方法

卸载期演示:

src/App.js

import Child from './Child';

class App extends Component {
  static defaultProps = {
    title: (() => {
      console.log(`defaultProps 初始期`)
      return 'app';
    })()
  }

  constructor(props) {
    super(props);
    this.state = {
      name: (() => {
        console.log(`this.state constructor时期`);
        return 'react'
      })()
    }
  }

  componentWillMount() {
    console.log(`componentWillMount 方法`)
  }

  componentDidMount() {
    console.log(`componentDidMount 方法`)
  }

  componentWillReceiveProps() {
    console.log(`componentWillReceiveProps 方法`)
  }

  shouldComponentUpdate() {
    console.log(`shouldComponentUpdate 方法`)
    return true;
  }

  componentWillUpdate() {
    console.log(`componentWillUpdate 方法`)
  }

  componentDidUpdate() {
    console.log(`componentDidUpdate 方法`)
  }

  componentWillUnmount() {
    console.log(`componentWillUnmount 方法`)
  }

  handleClick() {
    console.log(`点击了【按钮】`);
    this.setState({
      name: 'vue'
    })
  }

  render() {
    console.log(`render 方法`)
    return (
    <div>
      <button onClick={() => this.handleClick()}>按钮</button>
      <br />
      { this.state.name === 'react' ? <Child title={this.state.name}/> : null }
    </div>
    )
  }
}

export default App;

运行结果:

App.js:7 defaultProps 初始期
App.js:16 this.state constructor时期
App.js:23 componentWillMount 方法
App.js:59 render 方法
Child.jsx:7 constructor 方法
Child.jsx:14 componentWillMount 方法
Child.jsx:46 render 方法
Child.jsx:18 componentDidMount 方法
App.js:27 componentDidMount 方法
App.js:52 点击了【按钮】
App.js:35 shouldComponentUpdate 方法
App.js:40 componentWillUpdate 方法
App.js:59 render 方法
Child.jsx:42 componentWillUnmount 方法
App.js:44 componentDidUpdate 方法

各个回调方法的特性

constructor:

constructor函数是在对应组件初始化时调用的构造方法,构造方法就是该组件的出生方法,对应的对象只能出生一次,所以对应的实例组件一生只能调用一次,除非销毁重新生成。该方法的执行时间点是静态资源初始化执行后(static修饰的属性),componentWillMount方法执行前执行。constructor方法带有一个参数是props,参数props是父级中调用该组件时设置的属性集对象。该方法中第一行必须调用 super(props); 因为实现的组件都是继承自React.Compent对象,调用这个方法才能实现父组件props变化时自身渲染结果随之改变。

特性:

• 参数props父级传递下来的props对象
• constructor中必须写super(props)
• 组件初始化的时候调用,整个生命周期中只调用一次
• 在类中的静态资源加载完后执行(static defaultProps就是静态资源)

用途:

该方法的主要用途是用来初始化组件中的属性和定义属性的。所以我们一般都在这个方法中定义state中的属性,或定义一下实例变量。

componentWillMount

componentWillMount() 这个生命周期方法是React的第一个生命周期方法,该方法在组件对象的基础属性及方法都初始化完成后调用,调用这个方法就是说React开始准备接管这个对象了。

特性:

• 在组件挂载到DOM前调用,且只会被调用一次
• 调用this.setState不会引起组件重新渲染(此时还没有挂载到DOM上)

用途:

该方法中主要是初始化一下数据或在组件初始化的时候去请求数据。

componentDidMount

componentDidMount() 这个生命周期方法应该是用的最多的,一般用在进入页面后,数据初始化。componentDidMount与componentWillMount的区别是:componentWillMount是在render方法前调用的,componentDidMount是在render方法后调用的,render方法后对应的该组件就挂载到DOM上了,就可以完全被react接管了,此时可以调用this.setState方法了。

特性:

• 组件挂载到DOM后调用,且只会被调用一次
• 挂载到DOM后调用this.setState就会引起组件重新渲染

用途:

该方法中与componentWillMount用法差不多,但是这个方法中可以调用this.setState,可以重新渲染界面。

componentWillReceiveProps

componentWillReceiveProps(nextProps) 这个生命周期的方法是在组件挂载到DOM后属性变化后调用的。组件中的属性是由父组件中传递过来的值,在这个方法中可以判断父组件中传过来的值和该组件内值是否相等来判断是否指定属性改变了,来处理特定属性的行为。

特性:

• 参数是nextProps改变后的props对象
• 调用 this.setState不会引起第二次渲染,所以可以在此函数中根据props的变化设置state的值
• 当前组件中的this.props还是原来的值,还没有变化

用途:

该方法主要是来监控属性props的变化的,对特殊属性props的变化做出特别处理。可以过滤出对应属性变化来重新渲染组件,防止组件属性改变每次都渲染组件。

shouldComponentUpdate

shouldComponentUpdate(nextProps, nextState) 这个生命周期的方法是在props和state属性变化后都会调用的方法,用来判断是否需要重新渲染。此方法中的返回值用来决定是否重新渲染,返回true表示需要重新渲染,返回false反之。此方法返回true后会调用componentWillUpdate方法。

特性:

• 参数nextProps、nextState 分别表示变化后的props和state
• 当前组件中的this.props和this.state还是原来的值,还没有变化
• 可比较this.props、this.state和nextProps、nextState 中的值是否有变化
• 此函数return一个布尔值,表示是否需要重新渲染DOM

用途:

我们可以通过shouldComponentUpdate生命周期函数来来判断当前组件所在的props、state和context发生改变时,当前组件还是否需要进行更新操作(可以认为为当前组件自定义一个diff算法),以达到性能的最大优化。

componentWillUpdate

componentWillUpdate(nextProps, nextState) 这个生命周期的方法是在shouldComponentUpdate方法后调用,此方法调用后就会去调用render方法重新渲染界面。此方法中的参数是props变化后的值(父组件传递进来的值),该组件中的props还是原来的值还没有改变。

特性:

• 参数nextProps、 nextState 分别表示变化后的props和state
• 当前组件中的this.props和this.state还是原来的值,还没有变化
• 此方法在调用render方法前执行

用途:

DOM重新渲染前调用,用来查看界面最后渲染时值的前后变化。

componentDidUpdate

componentDidUpdate(prevProps, prevState) 这个生命周期的方法是在componentWillUpdate方法后调用过render后再调用。此方法调用后表示一个渲染过程完成。

特性:

• 参数prevProps, prevState 分别表示变化前的props和state
• 当前组件中的this.props和this.state的值已经变化
• 此方法掉用render方法后执行

用途:

DOM重新渲染后调用,可以用了查看渲染后属性值的前后变化。

componentWillUnmount

componentWillUnmount() 这个生命周期的方法是在组件销毁前调用。

特性:

• 此方法在组件被卸载前调用,可以在这里执行一些清理工作

用途:

组件销毁前做一些清理工作。如:clearTimeout, clearInterval

render

render() 方法用来重新渲染界面。

特性:

• 在componentWillMount后,componentDidMount前会被调用一次
• 在componentWillUpdate后,componentDidUpdate前会被调用
• 不能执行this.setState(会死循环)

相关文章
|
8天前
|
前端开发 JavaScript 测试技术
|
11天前
|
前端开发
react框架对Excel文件进行上传和导出
react框架对Excel文件进行上传和导出
|
11天前
|
前端开发 JavaScript vr&ar
|
19天前
|
前端开发 JavaScript 开发者
在React中,如何利用生命周期方法管理组件的状态和行为?
【5月更文挑战第29天】在React中,如何利用生命周期方法管理组件的状态和行为?
21 3
|
19天前
|
前端开发 JavaScript 调度
React的生命周期是什么
【5月更文挑战第29天】React的生命周期是什么
18 1
|
1月前
|
前端开发 网络架构 UED
React Next.js框架
React Next.js 是一个基于 React 的服务器渲染框架,用于构建高性能的现代Web应用。它提供内置的服务器渲染、静态导出、动态路由功能,并自动进行代码拆分。Next.js 还支持热模块替换、CSS-in-JS 和客户端路由,拥有丰富的插件生态系统,简化了开发过程,提升了应用的性能和用户体验。
|
1月前
|
前端开发 JavaScript API
blog-engine-07-gatsby 建极速网站和应用程序 基于React的最佳框架,具备性能、可扩展性和安全性。
探索多种博客引擎:Jekyll, Hugo, Hexo, Pelican, Gatsby, VuePress, Nuxt.js 和 Middleman。了解Gatsby,基于React的静态站点生成器,以其特性如React基础、静态生成、广泛插件支持、简便部署和现代开发流程脱颖而出。安装Gatsby需先安装Node.js,然后通过`gatsby-cli`创建新站点。开发涉及编写页面、本地开发、生成静态文件及部署。尽管Gatsby具有现代化和高性能优势,但也存在学习曲线和配置复杂性的挑战。
|
1月前
|
开发框架 前端开发 JavaScript
【专栏】对比分析两种流行的跨平台开发框架——Flutter和React Native,探讨它们的优势、劣势以及适用场景
【4月更文挑战第27天】本文对比分析了Flutter和React Native两大跨平台移动开发框架。Flutter,由Google推出,以其接近原生的性能、快速启动和流畅滚动受青睐,适合高性能和高度定制的项目。React Native,Facebook维护,依赖JavaScript,虽性能受限,但热重载优势和丰富第三方库使其适合快速迭代的项目。两者都在拓展多平台应用,Flutter在桌面和Web,React Native在Windows。选择框架需考虑项目需求、团队技能和性能效率平衡。
|
1月前
|
前端开发 JavaScript 定位技术
Docusaurus框架——react+antd+echarts自定义mdx生成图表代码解释文档
Docusaurus框架——react+antd+echarts自定义mdx生成图表代码解释文档
41 0
|
1月前
|
前端开发 JavaScript 搜索推荐
react-app框架——使用monaco editor实现online编辑html代码编辑器
react-app框架——使用monaco editor实现online编辑html代码编辑器
59 3