优化更新机制
在React默认更新机制中,默认的是只要一个组件的state发生变化,则该组件的所有子组件都会触发更新机制,如下面代码:Root的state只与A与A_1有关,与A_2和B无关
import React, { Component, Fragment } from 'react'
class A extends Component {
render() {
console.log('A组件更新了')
return (
<Fragment>
<A_1 data={this.props.data}/>
<A_2/>
</Fragment>
);
}
}
class A_1 extends Component {
render() {
console.log('A_1组件更新了')
return (
<div>
组件A_1
</div>
);
}
}
class A_2 extends Component {
render() {
console.log('A_2组件更新了')
return (
<div>
组件A_2
</div>
);
}
}
class B extends Component {
render() {
console.log('B组件更新了')
return (
<div>
组件B
</div>
);
}
}
class Root extends Component {
constructor() {
super()
this.state = {
data: 'xxx'
}
}
eventClick = () => {
this.setState({
data: 'xxxx'
})
}
render() {
return (
<Fragment>
<button onClick={this.eventClick}>更改root状态按钮</button>
<A data={this.state.data}/>
<B/>
</Fragment>
)
}
}
期望更新的状态是Root和A还有A_1触发更新,A_2和B不触发更新,但是实际上Root下的所有组件都会发生更新,即A_2和B的更新是无用的(绿色是期望render路径,红色是无用render)
![](https://img-blog.csdnimg.cn/20200916153121431.png)
![](https://img-blog.csdnimg.cn/20200916154132882.png#pic_center)
PureComponent
PureComponent
会自动识别哪些组件状态有更改并且只更新发生变化的组件,使用时只需把继承Component类换成继承PureComponent即可
import React, { PureComponent } from 'react'
class App extends PureComponent {
}
此时已经可以把A_2和B的render去掉了
![](https://img-blog.csdnimg.cn/20200916154512888.png#pic_center)
Component和PureComponent区别
继承Component时,只要state有发生改变,,就会触发重新渲染,而不管这个state里的内容是否会和原来一样
import React from 'react';
class App extends React.PureComponent {
constructor() {
super()
this.state ={
str: 'test'
}
}
eventClick = () => {
this.setState({
str: 'test'
})
}
render() {
console.log('已更新') // 点击时,只会打印一次'已更新',如果是继承Component,则点击一次打印一次
return (
<div >
<button onClick={this.eventClick}>test</button>
</div>
)
}
}
但是PureComponent
只能进行浅比较,当层级多(对象一级属性的value为引用类型)时则无法比较成功
import React from 'react';
class App extends React.PureComponent {
constructor() {
super()
this.state ={
obj: {
num : 1
}
}
}
eventClick = () => {
this.setState({
obj: {
num:1
}
})
}
render() {
console.log('已更新') // 无法判断出{num : 1}的内容是不变的,因此此时点击一次会打印一次
return (
<div >
<button onClick={this.eventClick}>test</button>
</div>
)
}
}
因此如果想完全做到渲染性能优化还是应该使用shouldComponentUpdate
重写重新渲染逻辑
shouldComponentUpdate
常规写法
shouldComponentUpdate(nextProps, nextState) {
return nextState.xxx !== this.state.xxx // 或者nextProps.xxx !== this.props.xxx
}
这里一般都需要指定到具体的值,因为如果没有设置state默认是null
,没有传props默认是{}
,null和{}的判断相等标准有所区别
if({} !== {}){
console.log('true') // 打印
}
if(null !== null) {
console.log('true') // 不打印
}
如下面例子,当在App类中设置了渲染更新标准时,即使不用PureComponent
,也不会多次执行更新渲染,同时也可以解决更深度的比较
import React from 'react';
class Demo extends React.Component {
constructor() {
super()
this.state ={
obj:{
str:'xxx'
}
}
}
shouldComponentUpdate(nextPops, nextState) {
return nextState.obj.str !== this.state.obj.str // 如果是 nextState.obj !== this.state.obj 则还是会多次渲染
}
eventClick = () => {
this.setState({
obj:{
str:'xxx'
}
})
}
render() {
console.log('已更新')
return (
<div >
<button onClick={this.eventClick}>test</button>
</div>
)
}
}
export default Demo