React组件的生命周期
前言
顾名思义生命周期就是一个React组件在运行时的周期历程,其本身是有一定的先后顺序的,也是有必要去先了解的。除了stateless 无状态组件外 React组件都有生命周期,因为他们都会经过实例化的过程以及销毁
生命周期分层
一般分为三大层
1. 初始化 挂载时
2. 数据更新时
3. 组件销毁时
首先时初始化
- constructor 定义state和获得props
constructor(props,context){
super(props,context)
this.state = {
xxx
}
}
一般这个时候是初始化状态
2. componentWillMount 组件将要挂载
componentWillMount(){
//这里尽量不要放延迟渲染的东西
//更不能在这里setState() 不是说不能 是不能写同步的setState
this.setState({foo:bar}) //错误 不会重新触发render
setTimeout(()=>{
this.setState({foo:bar}) //可以 但是没有多少必要
},0)
}
这是组件刚刚经历constructor数据初始完成
但是还未render,dom还未渲染
componentWillMount这里操作很少 尤其要注意,如果是非权限性dom渲染数据请求不要放在这里,因为会延迟dom的渲染,并且setState也不会在这里渲染
故要分清数据类型,比如说 登陆权限的获取等等 判断未登陆直接回退等等 但是用户数据的详情获取 就应该放在componentDidMount里
3. render
render(){
//这里可以计算一些东西,即每次dom渲染时需要计算的属性 如 列表啊 类名啊 等等东西 切记 一次性的东西不要放在这里
//render在props和state更新后若没有在shouldComponentUpdate阻止就会重新执行,比如一些插件初始化 数据的请求等等
return (
<div>
{dom} //dom
</div>)
}
react将jsx生成虚拟dom树然后更新dom
这里的render函数不是只执行一次,在之后的数据state,props的值变化过程中 这里是会重复调用的,即 dom变化和数据同步,所以有些一次性操作不应放置这里,这里应该是纯计算和渲染的东西
- componentDidMount
组件已经渲染到dom树了
componentWillMount(){
//数据获取
//计时器计时
//改变state
//等等操作 都可以
}
componentDidMount 时dom已经渲染到浏览器里的,这是的一些异步操作不会影响的其渲染了 所以故常常在这里 获取网路数据和计时器
以上四个就是react组件实例化的过程除了render其余的都只执行一边
数据更新
- componentWillReceiveProps
props变化时触发 除了首次渲染不执行
componentWillReceiveProps(nextProps){
//这是还Props变化还未渲染到dom中 只是数据变动
}
不知道大家有没有试过一个比较好玩的操作 在这里 触发事件改变父组件state 即props又改变 引起死循环的操作 栈溢出 所以在这里可以增加判断
- shouldComponentUpdate 在state props变化了 是否重新熏染
componentWillReceiveProps(nextprops,nextstate){
//无论是父组件变化 还事本身state变化 都会 触发这个函数 即 判断是否要进行更新渲染
if(newxprops.xxx===xxxx){
return false
}
}
一般情况下 本身state变化肯定是需要渲染的 但是父组件更新引起的重新渲染,虽然有diff算法,但是还是能优化的 故可以在次阻止无用的虚拟dom计算
- componentWillUpdate
componentWillUpdate(){
//这里同样不能用同setState同上
}
4.render函数重调用 生成虚拟dom树 进行diff算法对比
5. componentDidUpdate
componentDidUpdate(){
//组件已经更新
}
组件销毁
- componentWillUnmount
componentWillUnmount(){
clearInterval();
this.xx = null;
//销毁一些常驻内存的东西
}