16之前旧的生命周期:

16之后新的生命周期:
一、挂载期间:只调用一次
组件被实例化并挂载在到DOM树这一过程称为装载,在装载期调用的生命周期函数依次为
- **constructor:**初始化状态,进行函数的this绑定,只调用一次,
如果您不初始化状态并且不绑定方法,则无需为React组件实现构造函数。
但是若在构造函数中未调用super(props),this.props将在构造函数中未定义,造成错误。
作用:
-
通过将对象分配给来初始化本地状态 state。
-
给事件(方法)绑定this, 也就是把事件和方法绑定到创建好的组件实例上。
-
getDefaultProps()
设置默认的props,也可以用dufaultProps设置组件的默认属性。 *** getInitialState()** 初始化state,可以直接在constructor中定义this.state
- **componentWillMount():**组件初始渲染(render()被调用前)前调用,并且仅调用一次.可以修改state
- **render(): **创建虚拟dom,进行diff算法。
- **componentDidMount():挂载组件(插入树中)后立即调用,**组件第一次渲染完成,此时dom节点已经生成,可以在这里调用ajax请求,返回数据setState后组件会重新渲染,只调用一次
二、更新阶段(updateing)
- componentWillRecivedProps() : 老版本使用, 仅在父级更新导致重新渲染时才触发。
通过对比nextProps和this.props,将nextProps的state为当前组件的state,从而重新渲染组件。,一是根据 props 来更新 state,二是触发一些回调,如动画或页面跳转等。
//通过this.props来获取旧的外部状态,初始 props 不会被调用
//通过对比新旧状态,来判断是否执行如this.setState及其他方法
componentWillReceiveProps (nextProps) {
nextProps.openNotice !== this.props.openNotice&&this.setState({
openNotice:nextProps.openNotice
},() => {
console.log(this.state.openNotice:nextProps)
//将state更新为nextProps,在setState的第二个参数(回调)可以打印出新的state
})
}
- shouldComponentUpdate(nextProps, nextState):是否更新
组件挂载后(即执行完render),接收到新的state或props时被调用。返回true代表允许更新,返回false代表不允许更新。则不会走下面的更新生命周期函数。
- componentWillUpdate():重新渲染
shouldComponentUpdate返回true以后,组件进入重新渲染的流程,进入componentWillUpdate,这里同样可以拿到nextProps和nextState。
常见的 componentWillUpdate 的用例是在组件更新前,读取当前某个 DOM 元素的状态,并在 componentDidUpdate 中进行相应的处理。
- render():更新dom树
在此react会通过其diff算法比较更新前后的新旧DOM树,比较以后,找到最小的有差异的DOM节点,并重新渲染。
- componentDidUpdate(prevProps,prevState):更新发生(完成后)后立即调用。
你可以在这个方法中进行DOM操作,或者**做一些异步调用。**这个和首次装载过程后调用componentDidMount是类似的,不一样的是你可能需要判断下属性是否变化了再发起网络请求
三、卸载阶段Unmount()
卸载阶段:指组件从DOM树种移除。
- componentWillUnmount() : 组件将要挂载
你可以在这个函数中进行相关清理工作,比如删除定时器。但是不能操作state
componentWillUnmount() {
console.log('componentWillUnmount');
// 清除timer
clearInterval(this.timerID1);
clearTimeout(this.timerID2);
// 关闭socket
this.myWebsocket.close();
// 取消消息订阅...
}
四、错误捕获
- componentDidCatch(error, info):捕获错误
在react组件中如果产生的错误没有被被捕获会被抛给上层组件,如果上层也不处理的话就会抛到顶层导致浏览器白屏错误,在React16中我们可以实现这个方法来捕获子组件产生的错误,然后在父组件中妥善处理,比如搞个弹层通知用户网页崩溃等。
//error引发的错误, info具有componentStack键的对象,其中包含有关哪个组件引发了错误的信息
componentDidCatch(error, info) {
// Example "componentStack":
// in ComponentThatThrows (created by App)
// in ErrorBoundary (created by App)
// in div (created by App)
// in App
logComponentStackToMyService(info.componentStack);
}
React16中的生命周期函数变化:
componentWillMount,componentWillUpdate,
componentWillReceiveProps 被以下生命周期替代。
新增:
getDerivedStateFromProps(nextProps, prevState): 替代componentWillReceiveProps
static getDerivedStateFromProps(nextProps,prevState){
//该方法内禁止访问this
if(nextProps.email !== prevState.email){
//通过对比nextProps和prevState,返回一个用于更新状态的对象
return {
value:nextProps.email
}
}
//不需要更新状态,返回null
return null
}
这两者最大的不同就是:在 componentWillReceiveProps 中,我们一般会做以下两件事,一是根据 props 来更新 state,二是触发一些回调,如动画或页面跳转等。
在老版本的 React 中,这两件事我们都需要在 componentWillReceiveProps 中去做。
如:
class ExampleComponent extends React.Component {
state = {
isScrollingDown: false,
};
componentWillReceiveProps(nextProps) {
if (this.props.currentRow !== nextProps.currentRow) {
// 检测到变化后更新状态、并请求数据
this.setState({
isScrollingDown: nextProps.currentRow > this.props.currentRow,
});
this.loadAsyncData()
}
}
loadAsyncData() {/* ... */}
}
而在新版本中,官方将更新 state 与触发回调重新分配到了 getDerivedStateFromProps 与 componentDidUpdate 中,使得组件整体的更新逻辑更为清晰。而且在 getDerivedStateFromProps 中还禁止了组件去访问 this.props,强制让开发者去比较 nextProps 与 prevState 中的值,以确保当开发者用到 getDerivedStateFromProps 这个生命周期函数时,就是在根据当前的 props 来更新组件的 state,而不是去做其他一些让组件自身状态变得更加不可预测的事情。
如: getDerivedStateFromProps 是否更新, componentDidUpdate做需要更新的操作
class ExampleComponent extends React.Component {
state = {
isScrollingDown: false,
lastRow: null,
};
static getDerivedStateFromProps(nextProps, prevState) {
// 不再提供 prevProps 的获取方式
if (nextProps.currentRow !== prevState.lastRow) {
return {
isScrollingDown: nextProps.currentRow > prevState.lastRow,
lastRow: nextProps.currentRow,
};
}
// 默认不改动 state
return null;
}
componentDidUpdate() {
// 仅在更新触发后请求数据
this.loadAsyncData()
}
loadAsyncData() {/* ... */}
}
getSnapshotBeforeUpdate(prevProps, prevState)
作为componentDidUpdate的第三个参数。该函数与 componentDidUpdate 一起使用可以取代 componentWillUpdate 的所有功能。
这两者的区别在于:
在 React 开启异步渲染模式后,在 render 阶段读取到的 DOM 元素状态并不总是和 commit 阶段相同,这就导致在componentDidUpdate 中使用 componentWillUpdate 中读取到的 DOM 元素状态是不安全的,因为这时的值很有可能已经失效了。
getSnapshotBeforeUpdate 会在最终的 render 之前被调用,也就是说在 getSnapshotBeforeUpdate 中读取到的 DOM 元素状态是可以保证与 componentDidUpdate 中一致的。此生命周期返回的任何值都将作为参数传递给componentDidUpdate()。componentDidUpdate第三个参数。
该方法的触发时间为update发生的时候,在render之后dom渲染之前返回一个值,作为componentDidUpdate的第三个参数。该函数与 componentDidUpdate 一起使用可以取代 componentWillUpdate 的所有功能,比如以下是官方的例子:
常用生命周期函数:
-
constructor: 初始化状态,进行函数绑定
-
componentDidMount: 进行DOM操作,进行异步调用初始化页面
-
componentWillReceiveProps: 根据props更新状态
-
componentWillUnmount: 清理组件定时器,网络请求或者相关订阅等