在之前的React类式组件定义的时候,有说到有一个必不可少的内容,即render 函数,这个函数是React自带的,每当组件的状态变化的时候,就会触发一次render。
render函数就是React生命周期中的一个,与之类似的这些函数通常被称作React生命周期函数、React生命周期钩子函数、React生命周期钩子、React生命周期回调函数。
这些函数包括constructor、componentWillMount、render、componentDidMount、componentWillUnmount、componentWillReceiveProps、shouldComponentUpdate、componentWillUpdate、componentDidUpdate等。
constructor
constructor函数比较好理解,就是构造函数,也就是在组件被创建的一开始就调用。
在之前的内容中有说过,多数时候构造函数都是可以省略的。
但是需要注意的是,如果没有省略构造函数,那么构造函数中必须调用super 函数,同时,根据React官网的说明,规范的构造函数需要写props 参数,并将props 传给super ,否则的话可能导致一些问题。
componentWillMount和componentDidMount
之前在说虚拟DOM转换为真实DOM时,一直说的是渲染,实际上还有一个说法,是叫做挂载,英文单词也就是mount 。
所以实际上,也可以把初次render 就理解为是挂载,那么与之对应的就有另外两个生命周期函数,componentWillMount 和componentDidMount 。
这两个函数从命名就比较好理解,will是将要,did是完成,也就是说componentWillMount 指的是组件将要挂载前,componentDidMount 指组件完成挂载后。
说的再直白一点,就是componentWillMount 在初次render 之前调用,componentDidMount 在初次render 之后调用。
render
render是必不可少的一个生命周期函数,上边也说初次render 的时候就可以先理解为挂载。
但是为什么说初次呢,是因为挂载只有一次,而render却是1+n 次,只有第一次的时候可以简单理解为挂载。
除了刚开始加载的时候会调用,后边每次状态修改也都会触发render 。
componentWillUpdate和componentDidUpdate
说到状态修改时触发render ,自然就引出另两个生命周期函数,即componentWillUpdate 和componentDidUpdate 。
同样的,从命名就能比较容易理解作用,即组件将要修改前调用、组件修改后调用。
很显然,就是当修改类的render 触发时,在它之前和之后会分别触发componentWillUpdate 和componentDidUpdate 。
只是,这里少有一点问题,也就是说这个所谓的修改类操作,并不是真的一定是状态发生了修改。
状态发生修改这个可能比较好理解,因为在说state 的时候说过了,实际上指的就是setState 操作。
但是除了这个操作会触发修改类的render 外,还有一个操作也可以,那就是forceUpdate 。
他们的一个区别,就涉及到下一个生命周期函数。
shouldComponentUpdate
我们说setState 操作会引发状态的修改,但是状态修改了就一定会触发render 吗?
其实不是的。
因为在setState 和render 之前还有一个shouldComponentUpdate ,这个函数的作用说白了就是决定在setState 之后是否要进行render ,也就是一个开关。
在这个函数中,需要一个boolean 类型的返回值,默认情况下返回true,这也就是为什么之前只要setState 就一定会render 的原因。
setState 了不一定会render ,同样的,render 也不是必须要setState ,当执行了forceUpdate 后,也会触发render 。
如果说,setState 到render 的过程是shouldComponentUpdate ->componentWillUpdate ->render ,那么forceUpdate 的过程就是只有componentWillUpdate ->render 。
componentWillReceiveProps
上边几个声明周期函数都说完后,就剩componentWillReceiveProps 这一个了。
这个函数只有在父子组件关系中,且父组件第二次给子组件传递数据的时候才会触发。
例如有下边这段代码:
class Parent extends React.Component{
state={gift:"奥特曼"}
changeGift=()=>{
let {gift}=this.state
if(gift === '奥特曼'){
this.setState({gift:'超级飞侠'})
}else{
this.setState({gift:'奥特曼'})
}
}
render() {
let {gift}=this.state
return (
<div>
<h2>父组件</h2> <button onClick={this.changeGift}>点击换个礼物</button>
<Son gift={gift}></Son>
</div>
)
}
}
class Son extends React.Component{
componentWillReceiveProps(){
console.log("看下是什么礼物")
}
render(){
return (
<h3>{this.props.gift}</h3>
)
}
}
ReactDOM.render(<Parent />,document.getElementById('test'))
这段代码的意思是,有一个父组件,里边有一个按钮和一个子组件,父组件会给子组件传递一个礼物的数据,并且在点击按钮时修改传递的数据。
那么浏览器访问就会看到,一开始就会显示出奥特曼 ,当点击按钮的时候会在奥特曼 和
超级飞侠 之间切换。
如果打开浏览器控制台,就会进一步看到,当第一次访问的时候,并没有任何的输出内容,但是当点击按钮的时候,就会输出如下的内容:
|