概述
不管是vue还是React,它都有一个生命周期,它描述了组件从创建到销毁的整个生命过程,其中含有有很多的钩子函数连接而成。这里主要讲React新旧生命周期,以及他们的对比
生命周期(旧)
周期图如下 
其中左边是挂载时,右边是更新时,下边是更新时
挂载时
可以看出挂载时的更新数据顺序依次如下 1)constructor:构造器 2)componentWillMount:组件将要挂载 3)render:渲染 4)componentDidMount:组件挂载完成
可以通过代码来进行验证
class Life extends React.Component{
constructor(props){
super(props)
console.log("constructor");
}
componentWillMount(){
console.log("componentWillMount");
}
render(){
console.log("render");
return(
<div>
<button onClick={this.remove}>卸载组件</button>
</div>
)
}
componentDidMount(){
console.log("componentDidMount");
}
componentWillUnmount(){
console.log("componentWillUnmount");
}
remove=()=>{
ReactDOM.unmountComponentAtNode(document.getElementById("root"))
}
}
ReactDOM.render(<Life/>,document.getElementById("root"))
打印结果如图  当然这并不和函数声明顺序有关,这里不更改顺序做演示。
更新时
 由图可知更新时一共有三条可走的线路,分别是父组件render、setState、forceUpdate
父组件render
如图中红线所示 就是指父组件引用了子组件时,子组件更新数据的生命周期。 可以看到它的生命周期如下
1)componentWillReceiveProps:组件将要接收属性 2)shouldComponentUpdate:组件是否应该更新 3)componentWillUpdate:组件将要更新 4)componentDidUpdate:组件完成更新 注意: 这里shouldComponentUpdate相当于一个阀门,其返回值是一个布尔值,决定了是否继续后面的执行,其默认值为true
这里举一个例子: 需求: 父组件Father引用子组件Son,并将父组件state里的movie属性传给子组件,子组件通过props引用movie属性,然后通过点击父组件内的changeMovie更改movie属性状态,从而观察子组件更新时生命周期 
代码:
class Father extends React.Component{
state={
movie:"哥斯拉大战金刚"
}
changeMovie=()=>{
this.setState({
movie:this.state.movie==="哥斯拉大战金刚"?"复仇者联盟":"哥斯拉大战金刚"
})
}
render(){
const {movie}=this.state
return (
<div>
<Son movie={movie}/>
<button onClick={this.changeMovie}>切换电影</button>
</div>
)
}
}
class Son extends React.Component{
componentWillReceiveProps(){
console.log("componentWillReceiveProps");
}
shouldComponentUpdate(){
console.log("shouldComponentUpdate");
return true
}
componentWillUpdate(){
console.log("componentWillUpdate");
}
render(){
console.log("render");
const {movie}=this.props
return(
<div>
电影:{movie}
</div>
)
}
componentDidUpdate(){
console.log("componentDidUpdate");
}
}
ReactDOM.render(<Father/>,document.getElementById("root"))
打印结果如下 
setState
 如图中黄线所示 通过setState来更新数据是最常见的 1)shouldComponentUpdate:组件是否应该更新 2)componentWillUpdate:组件将要更新 3)componentDidUpdate:组件完成更新
通过一个简单的计数器演示 当数据改变,调用setState后打印更新周期  代码:
class Life extends React.Component{
state={
count:0
}
add=()=>{
this.setState({
count:this.state.count+1
})
}
shouldComponentUpdate(){
console.log("shouldComponentUpdate");
return true
}
componentWillUpdate(){
console.log("compontWillUpdate");
}
render(){
console.log("render");
const {count}=this.state
return (
<div>
<h2>计数:{count}</h2>
<button onClick={this.add}>加一</button>
</div>
)
}
componentDidUpdate(){
console.log("componentDidUpdate");
}
}
ReactDOM.render(<Life/>,document.getElementById("root"))
forceUpdate
如绿线所示 forceUpdate,顾名思义,强制更新。从图中也可以看出,其跳过了阀门,直接进行更新了 还是以计数器为例,不过增加了一个强制更新  可以看到这里给阀门关闭后,加一只输出shouldComponent,而强制加一后发生更新
class Life extends React.Component{
state={
count:0
}
add=()=>{
this.setState({
count:this.state.count+1
})
}
force=()=>{
this.setState({
count:this.state.count+1
})
this.forceUpdate()
}
shouldComponentUpdate(){
console.log("shouldComponentUpdate");
return false
}
componentWillUpdate(){
console.log("compontWillUpdate");
}
render(){
console.log("render");
const {count}=this.state
return (
<div>
<h2>计数:{count}</h2>
<button onClick={this.add}>加一</button>
<button onClick={this.force}>强制加一</button>
</div>
)
}
componentDidUpdate(){
console.log("componentDidUpdate");
}
}
ReactDOM.render(<Life/>,document.getElementById("root"))
卸载时
componentWillUnmount:组件将要卸载时 组件卸载前调用的钩子函数,可以通过调用ReactDOM.unmountComponentAtNode函数检验
生命周期(新)
 可以看到新的生命周期如上 由于例子差不多,不做演示
挂载时
1)constructor:构造器 2)getDerivedStateFromProps:从属性中得到派生的状态 3)render:渲染 4)componentDidMount:组件完成挂载
更新时
1)getDerivedStateFromProps:从属性中得到派生的状态 2)getSnapshotBeforeUpdate:更新前得到快照 3)componentDidUpdate:组件完成更新
卸载时
componentWillUnmount:组件将要卸载时
新旧生命周期的对比
1)可以看出,新生命周期中去掉了三个will钩子函数,分别是componentWillMount、componentWillUpdate、componentWillReceiveProps
原因查官方文档可知:这些生命周期方法经常被误解和滥用;此外,我们预计,在异步渲染中,它们潜在的误用问题可能更大。我们将在即将发布的版本中为这些生命周期添加 “UNSAFE_” 前缀。(这里的 “unsafe” 不是指安全性,而是表示使用这些生命周期的代码在 React 的未来版本中更有可能出现 bug,尤其是在启用异步渲染之后。)
2)新生命周期中新增getDerivedStateFromProps、getSnapshotBeforeUpdate 新的静态 getDerivedStateFromProps 生命周期方法在组件实例化之后以及重新渲染之前调用。它可以返回一个对象来更新 state,或者返回 null 来表示新的 props 不需要任何 state 的更新。
新的 getSnapshotBeforeUpdate 生命周期方法在更新之前(如:更新 DOM 之前)被调用。此生命周期的返回值将作为第三个参数传递给 componentDidUpdate。(通常不需要,但在重新渲染过程中手动保留滚动位置等情况下非常有用。)
|