React生命周期
初始化阶段
componentWillMount: render 之前最后一次修改状态的机会
render: 只能访问 this.props 和 this.state,不允许修改状态和 DOM 输出
componentDidMount: 成功 render 并渲染完成真实 DOM 之后触发,可以修改 DOM
运行中阶段
componentWillReceiveProps: 父组件修改属性触发
shouldComponentUpdate: 返回 false 会阻止 render 调用
componentWillUpdate: 不能修改属性和状态
render: 只能访问 this.props 和 this.state,不允许修改状态和 DOM 输出
componentDidUpdate: 可以修改 DOM
销毁阶段
- componentWillUnmount:在删除组件之前进行清理操作,比如计时器和事件监听
老生命周期的问题
(1) componentWillMount ,在 ssr 中 这个方法将会被多次调用, 所以会重复触发多遍,同时在这里如果绑定事件,将无法解绑,导致内存泄漏 , 变得不够安全高效逐步废弃。
(2) componentWillReceiveProps 外部组件多次频繁更新传入多次不同的 props,会导致不必要的异步请求
(3) componetWillupdate, 更新前记录 DOM 状态, 可能会做一些处理,与 componentDidUpdate 相隔时间如果过长, 会导致 状态不太信
新生命周期的替代
(1)getDerivedStateFromProps 第一次的初始化组件以及后续的更新过程中(包括自身状态更新以及父传子) ,返回一个对象作为新的 state,返回 null 则说明不需要在这里更新 state
//老的生命周期的写法
componentDidMount() {
if(this.props.value!==undefined){
this.setState({
current:this.props.value
})
}
}
componentWillReceiveProps(nextProps){
if(nextProps.value !==undefined){
this.setState({
current:nextProps.value
})
}
}
// 新的生命周期写法
static getDerivedStateFromProps(nextProps) {
if(nextProps.value!==undefined){
return {
current:nextProps.value
}
}
return null
}
(2) getSnapshotBeforeUpdate 取代了 componetWillUpdate ,触发时间为 update 发生的时候,在 render 之后 dom 渲染之前返回一个值,作为 componentDidUpdate 的第三个参数。
//新的数据不断插入数据前面, 导致我正在看的数据向下走,如何保持可视区依旧是我之前看的数据呢?
getSnapshotBeforeUpdate(){
return this.refs.wrapper.scrollHeight
}
componentDidUpdate(prevProps, prevState,preHeight) {
//if(preHeight===200)return ;
this.refs.wrapper.scrollTop +=this.refs.wrapper.scrollHeight-preHeight
}
<div style={{height:"200px",overflow:"auto"}}} ref="wrapper">
<ul>
.........
</ul>
</div>
react 中性能优化的方案
- shouldComponentUpdate
控制组件自身或者子组件是否需要更新,尤其在子组件非常多的情况下, 需要进行优化。
- PureComponent
PureComponent 会帮你 比较新 props 跟 旧的 props, 新的 state 和老的 state(值相等,或者
对象含有相同的属性、且属性值相等 ),决定 shouldcomponentUpdate 返回 true 或者
false, 从而决定要不要呼叫 render function。
注意:如果你的 state 或 props 『永远都会变』,那 PureComponent 并不会比较快,因为 shallowEqual 也需要花时间。