其实大部分团队不见得会跟进升到16版本,因此16前的生命周期仍是颇有必要掌握的,况且16也是基于以前的修改html
也就是如下代码中类的构造方法( constructor() ),Test类继承了react Component这个基类,也就继承这个react的基类,才能有render(),生命周期等方法可使用,这也说明为何函数组件不能使用这些方法
的缘由。react
super(props)
用来调用基类的构造方法( constructor() ), 也将父组件的props注入给子组件,功子组件读取(组件中props只读不可变,state可变)。
而constructor()
用来作一些组件的初始化工做,如定义this.state的初始内容。segmentfault
import React, { Component } from 'react'; class Test extends Component { constructor(props) { super(props); } }
在组件挂载到DOM前调用,且只会被调用一次,在这边调用this.setState不会引发组件从新渲染,也能够把写在这边的内容提早到constructor()中,因此项目中不多用。数组
根据组件的props和state(无二者的重传递和重赋值,论值是否有变化,均可以引发组件从新render) ,return 一个React元素(描述组件,即UI),不负责组件实际渲染工做,以后由React自身根据此元素去渲染出页面DOM。render是纯函数(Pure function:函数的返回结果只依赖于它的参数;函数执行过程里面没有反作用),不能在里面执行this.setState,会有改变组件状态的反作用。服务器
组件挂载到DOM后调用,且只会被调用一次async
在讲述此阶段前须要先明确下react组件更新机制。setState引发的state更新或父组件从新render引发的props更新,更新后的state和props相对以前不管是否有变化,都将引发子组件的从新render。详细可看这篇文章函数
父组件从新render引发子组件从新render的状况有两种,内容及代码修引自xiaoyann的回答性能
a. 直接使用,每当父组件从新render致使的重传props,子组件将直接跟着从新渲染,不管props是否有变化。可经过shouldComponentUpdate方法优化。优化
class Child extends Component { shouldComponentUpdate(nextProps){ // 应该使用这个方法,不然不管props是否有变化都将会致使组件跟着从新渲染 if(nextProps.someThings === this.props.someThings){ return false } } render() { return <div>{this.props.someThings}</div> } }
b.在componentWillReceiveProps方法中,将props转换成本身的statethis
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了,否则重复作同样的渲染了。
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> } }
此方法只调用于props引发的组件更新过程当中,参数nextProps是父组件传给当前组件的新props。但父组件render方法的调用不能保证重传给当前组件的props是有变化的,因此在此方法中根据nextProps和this.props来查明重传的props是否改变,以及若是改变了要执行啥,好比根据新的props调用this.setState出发当前组件的从新render
此方法经过比较nextProps,nextState及当前组件的this.props,this.state,返回true时当前组件将继续执行更新过程,返回false则当前组件更新中止,以此可用来减小组件的没必要要渲染,优化组件性能。
ps:这边也能够看出,就算componentWillReceiveProps()中执行了this.setState,更新了state,但在render前(如shouldComponentUpdate,componentWillUpdate),this.state依然指向更新前的state,否则nextState及当前组件的this.state的对比就一直是true了。
此方法在调用render方法前执行,在这边可执行一些组件更新发生前的工做,通常较少用。
render方法在上文讲过,这边只是从新调用。
此方法在组件更新后被调用,能够操做组件更新的DOM,prevProps和prevState这两个参数指的是组件更新前的props和state
此阶段只有一个生命周期方法:componentWillUnmount
此方法在组件被卸载前调用,能够在这里执行一些清理工做,好比清楚组件中使用的定时器,清楚componentDidMount中手动建立的DOM元素等,以免引发内存泄漏。
React v16.4 的生命周期图
React v16.4 的生命周期
原来(React v16.0前)的生命周期在React v16推出的Fiber以后就不合适了,由于若是要开启async rendering,在render函数以前的全部函数,都有可能被执行屡次。
原来(React v16.0前)的生命周期有哪些是在render前执行的呢?
若是开发者开了async rendering,并且又在以上这些render前执行的生命周期方法作AJAX请求的话,那AJAX将被无谓地屡次调用。。。明显不是咱们指望的结果。并且在componentWillMount里发起AJAX,无论多快获得结果也赶不上首次render,并且componentWillMount在服务器端渲染也会被调用到(固然,也许这是预期的结果),这样的IO操做放在componentDidMount里更合适。
禁止不能用比劝导开发者不要这样用的效果更好,因此除了shouldComponentUpdate,其余在render函数以前的全部函数(componentWillMount,componentWillReceiveProps,componentWillUpdate)都被getDerivedStateFromProps替代。
也就是用一个静态函数getDerivedStateFromProps来取代被deprecate的几个生命周期函数,就是强制开发者在render以前只作无反作用的操做,并且能作的操做局限在根据props和state决定新的state
React v16.0刚推出的时候,是增长了一个componentDidCatch生命周期函数,这只是一个增量式修改,彻底不影响原有生命周期函数;可是,到了React v16.3,大改动来了,引入了两个新的生命周期函数。
getDerivedStateFromProps
,getSnapshotBeforeUpdate
getDerivedStateFromProps
原本(React v16.3中)是只在建立和更新(由父组件引起部分),也就是否是不禁父组件引起,那么getDerivedStateFromProps也不会被调用,如自身setState引起或者forceUpdate引起。
React v16.3 的生命周期图
React v16.3
这样的话理解起来有点乱,在React v16.4中改正了这一点,让getDerivedStateFromProps不管是Mounting仍是Updating,也不管是由于什么引发的Updating,所有都会被调用,具体可看React v16.4 的生命周期图。
React v16.4后的getDerivedStateFromProps
static getDerivedStateFromProps(props, state) 在组件建立时和更新时的render方法以前调用,它应该返回一个对象来更新状态,或者返回null来不更新任何内容。
getSnapshotBeforeUpdate() 被调用于render以后,能够读取但没法使用DOM的时候。它使您的组件能够在可能更改以前从DOM捕获一些信息(例如滚动位置)。今生命周期返回的任何值都将做为参数传递给componentDidUpdate()。
官网给的例子:
class ScrollingList extends React.Component { constructor(props) { super(props); this.listRef = React.createRef(); } getSnapshotBeforeUpdate(prevProps, prevState) { //咱们是否要添加新的 items 到列表? // 捕捉滚动位置,以便咱们能够稍后调整滚动. if (prevProps.list.length < this.props.list.length) { const list = this.listRef.current; return list.scrollHeight - list.scrollTop; } return null; } componentDidUpdate(prevProps, prevState, snapshot) { //若是咱们有snapshot值, 咱们已经添加了 新的items. // 调整滚动以致于这些新的items 不会将旧items推出视图。 // (这边的snapshot是 getSnapshotBeforeUpdate方法的返回值) if (snapshot !== null) { const list = this.listRef.current; list.scrollTop = list.scrollHeight - snapshot; } } render() { return ( <div ref={this.listRef}>{/* ...contents... */}</div> ); } }