react v15
mark一下v15 react的几个生命周期函数:
1.componentWillMount
2.componentDidMount
3.componentWillReceiveProps
4.shouldComponentUpdate
5.componentWillUpdate
6.render
7.componentDidUpdate
8.componentWillUnmount
componentWillMount
有人会在这个方法里调用ajax来请求后端数据。这种做法是不妥的,原因如下:
1.会阻碍组件的实例化,影响组件渲染。渲染应该是纯粹的,不该触发I/O操作。
2.如果将ajax放在willMount中,可能会导致在一个尚未挂载的组件上进行setState,这可能会导致某些不确定隐患。在componentDidMount中执行ajax,将是十分安全的。
可以执行setState,但不建议这样做, 如果想在render之前指定state,应该使用default state
render
将jsx渲染到实际dom中
componentDidMount
在这个方法里,组件已经成功挂载,可以处理许多跟dom有关的操作,可以处理需要组件未挂载之前不能做的事情,比如事件监听。
可以调用setState,这里setState调用的效果会在下一次render进行。不理解?就是说如果这里进行了setState操作,会导致render执行两次。
componentWillReceiveProps
**首次渲染的时候,不会调用这个方法的,只有当后续props改变时才会执行。
一个典型使用场景是,通过对传入的props做处理,得到组件的state。比如一个tab选项卡,当前tab项应该是组件内部状态,但有时候业务要求可以任意指定当前选中tab,就需要根据传入的props做处理。
有些人会在这里diff新老props的不同,从而做些其他操作,比如动画。
严格说来这些都是副作用,应该尽力避免。这些副作用容易破坏state的,引入其他影响,可能导致组件状态变得不可预测。
可以setState
shouldComponentUpdate
禁止setState
很多人喜欢在这个地方来控制组件是否进行更新,来优化性能。
这里有另一种不同意见,过度使用这个特性可能会导致的问题。主要是scu会拖慢组件的更新速度,如果要比较的对象很大,比如层层嵌套的大家伙,很明显将会很耗时,假设比较花费了1ms,而直接渲染花费时间还不到1ms,那么个时候这种比较反而是累赘的,有副作用。请谨慎使用。
在比较两个层级比较复杂的对象时,这种比较就很难进行,因此引入了不可变数据–immutable。
componentWillUpdate
在组件更新之前执行,跟willReceiveProps的功能部分重复,除了这里不允许调用setState。willReceiveProps接受到了新的props,但组件并不一定会更新(scu),但willUpdate一定发生在render之前。因此如果组件里面存在scu方法,同时还想组件在更新之前做点什么的话,代码应该放在这里执行。
componentDidUpdate
可以调用setState,但要避免死循环。
这里可以进行一些dom相关操作,比如获取更新后的dom宽高。
componentWillUnmount
禁止setState
清理组件的残留,比如abort请求,解绑事件等
各生命周期是否可以调用setState方法
生命周期 | 是否允许调用setState | 备注 |
---|---|---|
WillMount | yes | 不建议调用 |
Didmount | yes | |
WillReceiveProps | yes | 不建议调用 |
scu | no | |
WillUpdate | no | |
DidUpdate | yes | |
WillUnmount | no |
react v16
react 16采用fiber架构实现了异步渲染,对原来的声明周期做了改变
逐步废弃了下面3个生命周期函数
componentWillMount
componentWillReceiveProps
componentWillUpdate
这3个函数都容易引发副作用,在15版本可能中这些副作用只是会影响性能;但在16的异步渲染模式中可能直接引起bug。
新增两个生命周期函数,以替代上面废弃的函数
static getDerivedStateFromProps
getSnapShortBeforeUpdate
渲染错误相关处理函数
static getDerivedStateFromError 专做UI降级处理
componentDidCatch 专做错误上报