React.PureComponent 和 forceUpdate 小结
在Vue中如果更改的data和上一次的data相同,vue便不会重新渲染,提高了性能。但在react中才不管是不是相同,只要状态更新便会重新渲染,为此React提供了一个生命周期钩子函数 shouldComponentUpdate( )这个钩子函数中接收最新的props和state但此时this上的props和state还未更新,于是我们就可以做一下判断, 如果this.props === ...
在Vue中如果更改的data和上一次的data相同,vue便不会重新渲染,提高了性能。
但在react中才不管是不是相同,只要状态更新便会重新渲染,为此React提供了一个生命周期钩子函数 shouldComponentUpdate( )这个钩子函数中接收最新的props和state但此时this上的props和state还未更新,于是我们就可以做一下判断, 如果this.props === props && this.state === state 则return false 代表此次不必要更新。否则return true。(当我们没有写shouldComponentUpdate时 React底层默认return true)
可以结合代码来理解一下
class ShouldUpdate extends Component {
shouldComponentUpdate (props, state) {
// isEqual 利用的是lodash工具库更新深拷贝的对比 也可以利用JOSN.stringify来转化成字符创比较 效果一样
if ( _.isEqual(props, this.props) && _.isEqual(state, this.state)) {
return false
}
return true
}
}
这样在属性或装填更新时 可以做一些拦截 避免不必要的更新。但我们最终的目的是提升新能,上面的两种方法都做了大量的比较,性能并不好。于是react也提供了一个方法来处理这个问题。
PureComponent
React.PureComponent
与React.Component
几乎完全相同,但React.PureComponent
通过prop和state的浅对比来实现shouldComponentUpate()
。
React.PureComponent
的shouldComponentUpdate()
只会对对象进行浅对比。如果对象包含复杂的数据结构,它可能会因深层的数据不一致而产生错误的否定判断(表现为对象深层的数据已改变视图却没有更新)。当你期望只拥有简单的props和state时,才去继承PureComponent
,或者在你知道深层的数据结构已经发生改变时使用forceUpate()
。或者,考虑使用 不可变对象 来促进嵌套数据的快速比较。
forceUpdate( )
component.forceUpdate(callback)
this.forceUpdate(callback) 来使用 强制更新 在需要强制更新的组件内使用
默认情况,当你的组件或状态发生改变,你的组件将会重渲。若你的
render()
方法依赖其他数据,你可以通过调用forceUpdate()
来告诉React组件需要重渲。调用
forceUpdate()
将会导致组件的render()
方法被调用,并忽略shouldComponentUpdate()
。这将会触发每一个子组件的生命周期方法,不覆盖子组件的shouldComponentUpdate()
方法。 若当标签改变,React仅会更新DOM。通常你应该尝试避免所有forceUpdate()
的用法并仅在render()
函数里从this.props
和this.state
读取数据。
import React ,{Component,PureComponent} from 'react'
class Son extends PureComponent {
constructor(props){
super(props)
this.state = {
style:{ width:'100px',
height:'100px',
background: this.props.color // props改变 state不会更新
}}
}
render(){
return(
<div style = {this.state.style}>
{console.log('Son render()')}
</div>
)
}
componentWillReceiveProps(props,state){
this.forceUpdate() // 每次传递属性时 都会强制渲染 并忽略shouldComponentUpdate
if ( props.color === this.props.color ) return false;
this.setState((pre)=>{
let newStyle = {...pre.style}
newStyle.background = props.color
console.log(props.color)
return {style:newStyle}
})
}
}
class Father extends Component {
constructor(){
super()
this.state = {
color :'pink'
}
}
changeColor = (color)=>{
this.setState({
color:color
})
}
render(){
return(
<>
{console.log('Father render')}
<button onClick = {this.changeColor.bind(null,'black')}>blcak</button>
<button onClick = {this.changeColor.bind(null,'pink')}>pink</button>
<button onClick = {this.changeColor.bind(null,'yellow')}>yellow</button>
<Son color = {this.state.color}></Son>
</>
)
}
}
export default Father
更多推荐
所有评论(0)