author huangteng
还有这个:
两个图其实表示的很清晰了,现在我们详细的解析React的生命周期。
首先,react的生命周期可以分为三个阶段:
初始化存在期销毁在源码里对应的就是MOUNTING、RECEIVE_PROPS、UNMOUNTING
图1、2中对初始化的过程描写的很清楚,就是3个方法完成4个步骤:
首先通过constructor方法完成对props和state的初始化。其中props是react从父组件继承过来的,state需要我们自己去定义。
接着是componentWillMount(),这个方法执行的时间点是在props和state初始化之后,render之前。这个时候可以在里面执行this.setState()操作,执行setState()并不会导致页面的渲染,只是单纯的state的合并操作。这个是初始化阶段在render之前最后一次可以修改组件state的机会。这个方法只执行一次,其实你们看图列也可以知道,初始化阶段的方法都是只执行一次的。这个方法相当于在组件渲染之前的准备工作。
render(),组件渲染,render应该保持为一个纯函数。不要在里面有操作DOM的Bug,只能通过this.props和this.state访问数据。可以返回null或者false。就是啥都不渲染嘛。
componentDidMount(),也是只执行一次。执行的时间点是在render之后。下一次重绘组件的入口之前。这个时候已经挂载到了DOM,所以在这个方法里面可以操作DOM,当然一般是通过ref进行。此时已可以使用其他类库来操作这个DOM。在服务端中,该方法不会被调用。当我们需要请求外部接口数据,一般都在这里处理(因为这里处理ajax,接下来的重绘(updating)阶段就可以直接用数据了)。但是在这里写一堆ajax你不觉得很混乱吗,交给redux吧。
首先在你第一次加载的时候,上述的初始化阶段一过去,就不会再有初始化这个阶段了,剩下的都是props和state的改变导致的不断updating的过程,所以我要说初始化的生命周期函数都是只执行一次呢。
这个时候我们的组件已经渲染出来了,用户也能够看到了,那么组件是不是就是一直不变了,那肯定是扯犊子嘛,随着用户的操作,比如点击按钮,发送信息啥的就会导致有新的props或者state从上层甚至上上层流入到我们刚刚新鲜出炉的组件里,这时就会触发组件的updating,导致UI视图的重绘。
触发的生命周期函数如下,这里要分两种情况。
如果是父组件传入了新的props,无论是传了新的key,还是原来的key赋予了新的value。这时会触发的是componmentWillReceiveProps(nextProps),记住哦,仔细看图1,如果仅仅state改变,props没变的时候,是不会触发这个生命周期函数了的,直接就跳过去进行shouldComponentUpdate()了。
当然如果没有props改变就是第二种情况,直接进行shouldComponentUpdate(),所以用componmentWillReceiveProps()是不是应该小小的考虑一下。
好,说清楚这个分叉的点,我们对componmentWillReceiveProps做个说明,首先这个函数执行的时机是父组件更新了子组件的props的时候,在这个函数里我们可以获取最新的props来更新props或者state。但是并不会导致重绘。
从state改变还是props改变分叉之后都会交汇到一点,shouldComponentUpdate,对没错,这个生命周期函数是重绘组件的阀门,它的返回值是一个boolean,默认返回true,如果返回false,那就简单多了,因为接下来的步骤都不会执行了,所以这是进行pureRender优化的函数,说白了就是进行deepCompare.当然这不是本章重点。
shouldComponentUpdate返true之后就会接着触发下一个生命周期函数
componmentWillUpdate(),其实和初始化阶段的componentWillMount差不多,就是重绘前的准备工作。唯一需要注意的是,这里面不能进行setState()或者更新props。因为这个函数自己就会把最新的state和props设置到this.state和this.props中,请把对state和props的更新放到componmentWillReceiveProps中好不。
然后是重绘(re-render)
最后是componmentDidUpdate()这个和componmentDidMount也差不多,也是可以获取真实DOM,可以用第三方库操作DOM
补充一点,updating期间的生命周期函数在初始化的时期是不会执行的哦。直白的说就比如componmentWillReceiveProps()函数肯定不会在你第一次初始加载组件的时候执行的。
销毁里面放一下清理工作,清除定时器啊之类的。略过。