react生命周期

参考链接
1.生命周期参考链接1
2.生命周期参考链接2

组件继承了react Component等相关基类,也就是继承了react的基类,才有render() , 生命周期等方法可以使用,这也说明了函数组件(无状态组件)不能使用这些方法的原因。

组件初始化阶段

类的构造方法(constructor())用来做组件的初始化工作

super(props)用来调用基类的构造方法,也将父组件的props注入给子组件,供子组件读取

组件中props只读不可变,state可变。

import React, { Component } from 'react';
class Test extends Component {
  constructor(props) {
    super(props);
  }
}
constructor(props) {
    super(props);
    this.comboxHtmlOut = this.props.comboxHtmlOut;
    this.pathQuery=this.props.pathQuery
  }
  state = {
    employeeData: {},
    submitLoading: false,
    selectData:[]
  };

constructor()接收两个参数props,context

可以获取到父组件传下来的props,context,如果想在constructor构造函数内部 (注意是内部哦,在组件其他地方是可以直接接收的)使用props或context,则需要传入,并传入super对象。

constructor(props,context) {
  super(props,context)
  console.log(this.props,this.context) // 在内部可以使用props和context
}

注意:只要组件存在constructor,就必须要写super,否则this指向就会错误

constructor() {
  console.log(this) // 报错,this指向错误
}

组件挂载阶段

此阶段分为componentWillMount , render , componentDidMOunt 三个时期

componentWillMount

在组件挂载到DOM前调用,且只会被调用一次,在这边调用this.setState不会引起组件重新渲染,也可以把写在这边的内容提前到constructor()中。

1)组件刚经过constructor初始完数据
2)组件未进入render,未完成渲染

注意:ajax请求不推荐写在这里
原因:
1)虽然有些情况下并不会出错,但是如果ajax请求过来的数据是空,那么会影响页面的渲染,可能看到的就是空白。(个人觉得只要做好相应的异常处理操作即可避免该问题)
2)不利于服务端渲染,在同构的情况下,生命周期会到componentwillmount,这样使用ajax就会出错

render

根据组件的props和state(只要两者重传递和重赋值,无论值是否有变化,都可以引起组件重新render),renter出一个react元素,不负责组件实际渲染工作,之后由React自身根据此元素去渲染出页面DOM。render是纯函数(Pure function:函数的返回结果只依赖于它的参数;函数执行过程里面没有副作用),不能在里面执行this.setState,会有改变组件状态的副作用。

render函数会插入jsx生成的dom结构,react会生成一份虚拟dom树,在每一次组件更新时,在此react会通过其diff算法比较更新前后的新旧DOM树,比较以后,找到最小的有差异的DOM节点,并重新渲染

react16中 render函数允许返回一个数组,单个字符串等,不在只限制为一个顶级DOM节点,可以减少很多不必要的div(当然注意升级你的react版本,将现有项目升到react16并不会出现什么bug,唯一注意的是proTypes类型检测换了名字~)

eg:

render () {
  return " "
}
render () {
  return [
              <div></div>
             <div></div>
          ]
}

componentDidMount

组件挂载到DOM后调用,且只会被调用一次

组件第一次渲染完成,此时dom节点已经生成,可以在这里调用ajax请求,返回数据setState后组件会重新渲染


组件更新阶段

setState引起的state更新或父组件重新render引起的props更新,更新后的state和props相对之前无论是否有变化,都将引起子组件的重新render。

组件更新两类(三种)情况:

1.父组件重新render

1)直接使用,每当父组件重新render导致的重传props,子组件将直接跟着重新渲染,无论props是否有变化。可通过shouldComponentUpdata方法优化。

class Child extends Component {
   shouldComponentUpdate(nextProps){ // 应该使用这个方法,否则无论props是否有变化都将会导致组件跟着重新渲染
        if(nextProps.someThings === this.props.someThings){
          return false
        }
    }
    render() {
        return <div>{this.props.someThings}</div>
    }
}

2)在componentWillReceiveProps方法中,将props转换成自己的state

class Child extends Component {
    constructor(props) {
        super(props);
        this.state = {
            someThings: props.someThings
        };
    }
    componentWillReceiveProps(nextProps) { // 父组件重传props时就会调用这个方法
        this.setState({someThings: nextProps.someThings});
    }
    render() {
        return <div>{this.state.someThings}</div>
    }
}

在该函数(componentWillReceiveProps)中调用 this.setState() 将不会引起第二次渲染

是因为componentWillReceiveProps中判断props是否变化了,若变化了,this.setState将引起state变化,从而引起render,此时就没必要再做第二次因重传props引起的render了,不然重复做一样的渲染了。

2.组件本身调用setState,无论state有没有变化。可通过shouldComponentUpdate方法优化。

class Child extends Component {
   constructor(props) {
        super(props);
        this.state = {
          someThings:1
        }
   }
   shouldComponentUpdate(nextStates){ // 应该使用这个方法,否则无论state是否有变化都将会导致组件重新渲染
        if(nextStates.someThings === this.state.someThings){
          return false
        }
    }

   handleClick = () => { // 虽然调用了setState ,但state并无变化
        const preSomeThings = this.state.someThings
         this.setState({
            someThings: preSomeThings
         })
   }

    render() {
        return <div onClick = {this.handleClick}>{this.state.someThings}</div>
    }
}

此阶段分为componentWillReceiveProps,shouldComponentUpdate,componentWillUpdate,render,componentDidUpdate

componentWillReceiveProps(nextProps)

此方法只调用于props引起的组件更新过程中,参数nextProps是父组件传给当前组件的新props。但父组件render方法的调用不能保证重传给当前组件的props是有变化的,所以在此方法中根据nextProps和this.props来查明重传的props是否改变,以及如果改变了要执行啥,比如根据新的props调用this.setState出发当前组件的重新render

componentWillReceiveProps在接受父组件改变后的props需要重新渲染组件时用到的比较多

它接受一个参数nextProps
通过对比nextProps和this.props,将nextProps setState为当前组件的state,从而重新渲染组件

componentWillReceiveProps (nextProps) {
    nextProps.openNotice !== this.props.openNotice && this.setState({
        openNotice:nextProps.openNotice
    },() => {
      console.log(this.state.openNotice:nextProps) //将state更新为nextProps,在setState的第二个参数(回调)可以打印出新的state
  })
}
 <BusinessRight
    filterId={this.state.rightFilterId}
 />
******************************************************
componentWillReceiveProps(nextProps) {
    if (nextProps.filterId !== this.props.filterId) {
      let filterParame={
        businessModelId:nextProps.filterId
      }
      this.setState({filterParame})
      this.reloadList(apiUrl.list,nextProps,undefined,filterParame)
    }
  }

shouldComponentUpdate(nextProps, nextState)

唯一用于控制组件重新渲染的生命周期,由于在react中,setState以后,state发生变化,组件会进入重新渲染的流程,(暂时这么理解,其实setState以后有些情况并不会重新渲染,比如数组引用不变)在这里return false可以阻止组件的更新

因为react父组件的重新渲染会导致其所有子组件的重新渲染,这个时候其实我们是不需要所有子组件都跟着重新渲染的,因此需要在子组件的该生命周期中做判断

此方法通过比较nextProps,nextState及当前组件的this.props,this.state,返回true时当前组件将继续执行更新过程,返回false则当前组件更新停止,以此可用来减少组件的不必要渲染,优化组件性能

对于react初学者,可能涉及这个生命周期的机会比较少,但是如果你的项目开始注重性能优化,随着你对react的喜爱和深入,你就会用到这个生命周期

componentWillUpdate(nextProps, nextState)

此方法在调用render方法前执行,在这边可执行一些组件更新发生前的工作,一般较少用。

shouldComponentUpdate返回true以后,组件进入重新渲染的流程,进入componentWillUpdate,这里同样可以拿到nextProps和nextState

render

render方法在上文讲过,这边只是重新调用。

componentDidUpdate(prevProps, prevState)

此方法在组件更新后被调用,可以操作组件更新的DOM,prevProps和prevState这两个参数指的是组件更新前的props和state

组件更新完毕后,react只会在第一次初始化成功会进入componentDidmount,之后每次重新渲染后都会进入这个生命周期,这里可以拿到prevProps和prevState,即更新前的props和state。


卸载阶段

此阶段只有一个生命周期方法:componentWillUnmount

componentWillUnmount

此方法在组件被卸载前调用,可以在这里执行一些清理工作,比如清楚组件中使用的定时器,清楚componentDidMount中手动创建的DOM元素等,以避免引起内存泄漏。

eg:

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

推荐阅读更多精彩内容