React生命周期

react 生命周期

生命周期图

生命周期经历三个过程

  • 装载过程(mount), 也就是把组件第一次在DOM树中渲染的过程
  • 更新过程(updata), 当组件被重新渲染的过程
  • 卸载过程(Unmount), 组件充DOM中删除的过程

三种不同的过程,React库会一次调用组件的一些成员函数,即生命周期钩子

装载过程中的生命周期钩子

constructor
getinitialState
getDefaultProps
componentWillMount
render
componentDidMount

getinitialState、getDefaultPropsReact.createClass创建组件时用到的生命周期函数,在高版本的React中已经放弃这种方法,所以这次就不进行展示;

constructor

在面向对象编程中,类(class)是对象(object)的模板,定义了同一组对象(又称"实例")共有的属性和方法。

Javascript语言不支持"类",但是可以用一些变通的方法,模拟出"类"。

阮一峰---js类

阮一峰---ES6 > Class

constructor ES6中每个类的构造函数,并不是每个组件都需要定义自己的构造函数,无状态的React组件往往不需要定义构造函数,一个React组件需要构造函数,往往是为了下面的目的

  • 初始化state,因为组件生命周期中任何函数都可以访问state,那么整个生命周期中第一个被调用构造函数自然是初始化state最理想的地方
  • 绑定成员函数的this

在ES6语法下,类的每个成员函数在执行时this应不是和类实例自动绑定的,而是在构造函数中,this就是当前组件实例,所以为了方便将来的调用,往往在构造函数中将这个实例的特定函数绑定this为当前实例

    this.count = this.count.bind(this)

render

render 函数无疑是React组件中最重要的函数,一个React组件可以忽略其他所有函数都不实现,但是一定要实现render函数,因为React组件的父类React.Component类对除了render之外的生命周期都有默认实现

render 函数并不做实际的渲染动作,它返回一个JSX的描述的结构,最容由React来操作渲染过程

某些特殊组件的作用不是渲染洁面,或者,组件在某些情况下没有什么内容取进行更新,那么让render函数返回一个null或者false,等于告诉React,这次组件不需要渲染任何DOM元素

注意: render 函数应是一个纯函数,完全根据this.statethis.props 来决定返回的结果,而且不要产生任何副作用。在render函数中取调用this.setState毫无疑问是错误的,因为一个纯函数不应该引起状态的改变

componentWillMoun和componentDidMount

在装载过程中,componentWillMount会在调用render函数前被调用,componentDidMount则会在调用render函数后被调用,正好分别来做render前后必备的工作;

componentWillMount 放生在"将要装载"的时候;这个时候没有任何渲染出来的结果,即使调用this.setState修改状态也不会引发重新绘制,因为一切都晚了,在这个时候可以做的事情都可以放到constructor中,可以认为这个函数存在的主要目的是和componentDidMount对称;

componentDidMount 调用在render函数被调用完之后,componentDidMount被调用的时候,render函数返回的东西已经引发了渲染,组件已经被"装载"到DOM树上;值得注意的时,render函数被调用后,componentDidMount函数并不是马上被渲染;

代码如下:
import React, { Component } from 'react';
import Counter from './Counter';  
// app.js
class App extends React.Component {
  render() {
    console.log('enter ControlPanel render')
    return (
      <div className="App" >
        <div style={{border: '1px solid', textAlign: 'center'}}>
        <Counter caption="First" initValue={0}/>
        <Counter caption="Second" initValue={10} />
        <Counter caption="Third" initValue={20} />
        </div>
      </div>
    )
  }
}
// Counter.js
import React, { Component } from 'react';
class Counter extends Component {
  constructor(props) {
    super(props);
    this.state = {
      count: this.props.initValue,
      name: this.props.caption
    }
  }
  componentWillMount () {
    console.log('render 运行前': this.state.name)
  }
  componentDidMount () {
    console.log('render 运行后': this.state.count)
  }
  render () {
    retrun (
      <div>{this.state.name}: {this.state.count}<div>
    )
  }
}

结果:

componentDidMount 并不会直接运行

可以清除的看到,componentDidMount是当三个组件都调用完成后,才一起被调用;
因为render函数本身并不往DOM树上渲染或者装载内容,它返回的是一个JSX表示的对象,然后由React库根据返回对象决定如何渲染,而React库把所有组件返回的结果综合起来,才知道如何产生对应的DOM修改,所以React库调用Counter三个组件的render函数后,才有可能完成状态,这个时候才会依次调用组件的componentDIdMount函数;

更新过程

componentWillReceiveProps
shouldComponentUpdate
componentWillUpdate
render
componentDidUpdate

componentWillReceiveProps

只要父组件的render函数被调用,在render函数里面被渲染的子组件就会经历更新过程,不管父组件传给子组件的props有没有改变,都会触发子组件的componentWillReceiveProps函数。

// 代码 接上部分代码
// app.js
<button onClick={() => this.forceUpdate()}>aaaa</button>
// Counter.js
 componentWillReceiveProps (nextProps) {
    console.log('enter componentReceiveProps' + this.props.name)
 }
父组件render被调用

shouldComponentUpdate(nextProps, nextState)

除了render函数外,shouldCompoentUpdate可能是整个组件生命周期中最重要的一个函数了;

shouldCompoentUpdate函数决定了一个组件什么时候不需要进行渲染;

shouldCompoentUpdaterender是React生命周期函数中唯二两个要求有返回结果的函数,render返回结果将用于构造DOM对象,而shouldCompoentUpdate函数返回一个布尔值,告诉React库这个组件在本次更新中国呢是否继续;

在React库首先调用shouldCompoentUpdate 函数,如果返回true则仅需更新,调用render,如果返回false则停止更新过程,也不会引发后续渲染。

// 代码接上面
// Counter.js
shouldComponentUpdate(nextProps, nextState) {
        return (nextProps.count !== this.props.count) || (nextState.count !== this.state.count)
}
componentWillUpdate () {
    console.log('componentWillUpdate')
}
componentDidUpdate () {
    console.log('componentDidUpdate')
}

当点击aaaa进行刷新时,不会调用shouldComponentUpdate,同时也不会进行componentWillUpdate函数等的调用,当进行加减操作石,则触发;

componentWillUpdate和componentDidUpdate

componentWillUpdate 组件初始化时不调用,只有在组件将要更新时才调用,此时可以修改state

componentDidUpdate 组件初始化时不调用,组件更新完成后调用,此时可以获取dom节点。

卸载过程

componentWillUnmount

防止内存泄漏
用法官方实例

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,362评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,330评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,247评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,560评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,580评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,569评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,929评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,587评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,840评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,596评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,678评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,366评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,945评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,929评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,165评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,271评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,403评论 2 342

推荐阅读更多精彩内容