React.Component与React.PureComponent

该文章发布于 ,归类于 Javascript

官方文档上这样介绍

React.PureComponent 类似于 React.Component。它们的不同之处在于React.Component 没有实现 shouldComponentUpdate(),但是 React.PureComponent实现了它。采用对属性和状态用浅比较的方式。

所以,他们的不同之处就在于,React.PureComponent使用的是对象的浅比较,而React.Component使用的是深层比较。

例如对数组的操作,如果使用pop()shift(), splice()等等这些操作,它的引用地址是不会发生变化的,浅比较只会比较它们的引用地址,所以React就认为它没有发生变化。比如如下例子:

class TestApp extends React.PureComponent {
  constructor(props) {
    super(props);
    this.state = {
      items: Array.from({ length: 6 }).map((_, i) => i + 1)
    };
  }

  handleClick(i) {
    const { items } = this.state;
    items.splice(i, 1);
    this.setState({ items });
  }

  render() {
    return (
      <div>
        <ul>
          {this.state.items.map((item, i) => (
            <li key={i}>
              {item} <button onClick={() => this.handleClick(i)}>x</button>
            </li>
          ))}
        </ul>
      </div>
    );
  }
}

这时候,点击“x”你会发现DOM上的li列表内容并没有减少,可是items数组却在不断减少。那么,如果此时你知道数据发生了变化,想让React对渲染进行更新,可以手动调用forceUpdate()来强制更新。

handleClick(i) {
  const { items } = this.state;
  items.splice(i, 1);
  this.setState({ items });
  this.forceUpdate()
}

如果继承自React.Component就会进行深层比较,就没有必要再调用forceUpdate()这个方法来强制更新了。

使用React.PureComponent可以对性能进行一些优化。如果使用React.Component它会对所有的属性都进行一次变动检测,会带来不必要的性能损耗,假如我只想在特定的几个属性发生变化的时候对dom进行更新,只需要在shouldComponentUpdate钩子检测必要变动进行更新,来达到性能优化的目的。

这里简单以上述例子为例:

class TestApp extends React.Component {

  // some codes...

  shouldComponentUpdate(nextProps, nextState) {
    return this.state.items.length === nextState.items.length;
  }

  // some codes...
}

通过检测itemslength变动来告诉React应该重新渲染dom。

所以,为了能够达到更好的渲染性能,在当你知道你的数据只是简单的数据类型时,可以使用React.PureComponent,如果存在复杂数据类型,则要考虑使用React.Component,必要时可以在shouldComponentUpdate钩子中检测特定数据变动来触发更新。

相关文章