forceUpdate()方法:
Sub.js
class Sub extends React.Component{
construcotr(){
super();
this.name = "yema";
}
refChangeName(name){
this.name = name;
this.forceUpdate();
}
render(){
return (<div>{this.name}</div>);
}
}
App.js
class App extends React.Component{
handleClick(){
this.subRef.refChangeName("yemafuren");
}
render(){
return (<div>
<Sub ref={(sub)=>{this.subRef = sub;}} />
<button onClick={this.handleClick}>click</button>
</div>);
}
} 在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
}
}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