组件更新机制
- setState() 的两个作用:1.修改 state 2.更新组件(UI)
- 过程:父组件重新渲染时,也会重新渲染子组件,但只会渲染当前组件的所有子组件
性能优化
1. 减轻 state
- 只存储各组件渲染相关的数据(比如:count、列表数据、loading等)
- 注意:不做渲染的数据不要放在 state 中
- 对于这种需要在多个方法中用到的数据,应该放在 this 中
class Hello extends Component {
conponentDidMount(){
// timer 存储在 this 中,而不是 state 中
this.timerId = setInterval(()=>{},2000)
}
componentWillUnmount(){
clearInterval(this.timerId)
}
render(){...}
}
2. 避免不必要的重新渲染 ( shouldComponentUpdate )
- 组件更新机制:父组件更新会引起子组件也被更新
- 问题:子组件没有任何变化时也会重新渲染
- 如何避免不必要的渲染呢?
- 解决方式:使用钩子函数 shouldComonentUpdate(nexProps,nextState)
- 作用:通过返回值决定该组件是否重新渲染,返回 true 表示重新渲染,false则不渲染
- 触发时机:更新阶段的钩子函数,组件重新渲染前执行(shouldComponentUpdate > render)
class Hello extends Component {
shouldComponentUpdate(newProps,newState){
// newProps.xxx === this.props.xxx
// newState.xxx === this.state.xxx
return false
}
render(){return(...)}
}
3. 纯组件
- 说明:纯组件内部的对比是 shallow compart (浅层对比)
- 对于值类型来说:比较两个值是否相同(直接复制即可)
let number = 0
let newnumber= number
newNumber = 2
console.log(number === newNumber) // falsestate = {number : 0}
setState({
number: Math.floor(Math.rendom() * 3)
})
// PureComponent 内部对比
最新的state.name === 上一次的 state.number // false, 重新渲染组件
- 对于引用类型来说:值比较对象的引用(地址)是否相同
- 注意:state 或 props 中属性值为引用了类型时,应该创新新数据,不要直接修改原数据
// 正确 创建新数据
const newObj = {...state.obj,number:2}
setState({ obj : newObj })
// 正确 创建新数据
/*不要用数组的push / unshift 等直接修改当前数组的方法*/
/*而应该用 cocat 或 slice 等API返回新数组*/
this.setState({
list:[...this.state.list,{新数据}]
})