ホームページ  >  記事  >  ウェブフロントエンド  >  React の PureComponent の概要

React の PureComponent の概要

不言
不言オリジナル
2018-07-09 16:26:551590ブラウズ

この記事では主に React での PureComponent の導入について紹介します。これを必要な友達に共有します。

React はレンダリングされた UI 内で確立され、維持されます。コンポーネントから返された React 要素を含む内部層の実装。この実装により、React は、JavaScript オブジェクトを直接操作するよりも時間がかかる可能性があるため、DOM ノードの不必要な作成と関連付けを回避できます。これは「仮想 DOM」と呼ばれます。

コンポーネントの props または state が変化すると、React は新しく返された要素を以前にレンダリングされた要素と比較することによって、実際の DOM を更新する必要があるかどうかを判断します。それらが等しくない場合、React は DOM を更新します。

場合によっては、再レンダリング プロセスが開始される前にトリガーされるこのライフサイクル関数 shouldComponentUpdate をオーバーライドすることで、コンポーネントの速度を向上させることができます。 この関数はデフォルトで true を返し、React が更新を実行できるようにします:

shouldComponentUpdate(nextProps, nextState) {
  return true;
}

props.color または state.count の変更 レンダリングするには、次のように <code> shouldComponentUpdate を設定します:

class CounterButton extends React.Component {
  constructor(props) {
    super(props);
    this.state = {count: 1};
  }

  shouldComponentUpdate(nextProps, nextState) {
    if (this.props.color !== nextProps.color) {
      return true;
    }
    if (this.state.count !== nextState.count) {
      return true;
    }
    return false;
  }

  render() {
    return (
      <button
        color={this.props.color}
        onClick={() => this.setState(state => ({count: state.count + 1}))}>
        Count: {this.state.count}
      </button>
    );
  }
}

上記のコードでは、 shouldComponentUpdateprops.color のみをチェックし、 state.count の変更。これらの値が変更されない場合、コンポーネントは更新されません。コンポーネントがより複雑になると、同様のパターンを使用してプロパティと値の「浅い比較」を実行し、コンポーネントを更新する必要があるかどうかを判断できます。このパターンは非常に一般的であるため、React はこのロジックを実装するためのヘルパー オブジェクトを提供します (React.PureComponent から継承)。次のコードは、同じ操作をより簡単に実現できます: props.color或者state.count的值变化时重新渲染,你可以像下面这样设定shouldComponentUpdate

class CounterButton extends React.PureComponent {
  constructor(props) {
    super(props);
    this.state = {count: 1};
  }

  render() {
    return (
      <button
        color={this.props.color}
        onClick={() => this.setState(state => ({count: state.count + 1}))}>
        Count: {this.state.count}
      </button>
    );
  }
}

在以上代码中,shouldComponentUpdate只检查props.colorstate.count的变化。如果这些值没有变化,组件就不会更新。当你的组件变得更加复杂时,你可以使用类似的模式来做一个“浅比较”,用来比较属性和值以判定是否需要更新组件。这种模式十分常见,因此React提供了一个辅助对象来实现这个逻辑 - 继承自React.PureComponent。以下代码可以更简单的实现相同的操作:

if (this._compositeType === CompositeTypes.PureClass) {
    shouldUpdate = !shallowEqual(prevProps, nextProps) || !shallowEqual(inst.state, nextState);
}

PureComponent

原理

当组件更新时,如果组件的 props 和 state 都没发生改变, render 方法就不会触发,省去 Virtual DOM 的生成和比对过程,达到提升性能的目的。具体就是 React 自动帮我们做了一层浅比较:

class ListOfWords extends React.PureComponent {
  render() {
    return <p>{this.props.words.join(',')}</p>;
  }
}

class WordAdder extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      words: ['marklar']
    };
    this.handleClick = this.handleClick.bind(this);
  }

  handleClick() {
    // This section is bad style and causes a bug
    const words = this.state.words;
    words.push('marklar');
    this.setState({words: words});
  }

  render() {
    return (
      <p>
        <button onClick={this.handleClick} />
        <ListOfWords words={this.state.words} />
      </p>
    );
  }
}

而 shallowEqual 又做了什么呢?会比较 Object.keys(state | props) 的长度是否一致,每一个 key 是否两者都有,并且是否是一个引用,也就是只比较了第一层的值,确实很浅,所以深层的嵌套数据是对比不出来的。

问题

大部分情况下,你可以使用React.PureComponent而不必写你自己的shouldComponentUpdate,它只做一个浅比较。但是由于浅比较会忽略属性或状态突变的情况,此时你不能使用它。

handleClick() {
  this.setState(prevState => ({
    words: prevState.words.concat(['marklar'])
  }));
}

或者

handleClick() {
  this.setState(prevState => ({
    words: [...prevState.words, 'marklar'],
  }));
};

或者针对对象结构:

function updateColorMap(oldObj) {
  return Object.assign({}, oldObj, {key: new value});
}

在ListOfWords中,this.props.words是WordAdder中传入的其state的一个引用。虽然在WordAdder的handelClick方法中被改变了,但是对于ListOfWords来说,其引用是不变的,从而导致并没有被更新。

解决方法

在上面的问题中可以发现,当一个数据是不变数据时,可以使用一个引用。但是对于一个易变数据来说,不能使用引用的方式给到PureComponent。简单来说,就是我们在PureComponent外层来修改其使用的数据时,应该给其赋值一个新的对象或者引用,从而才能确保其能够进行重新渲染。例如上面例子中的handleClick可以通过以下几种来进行修改从而确认正确的渲染:

// 常见的js处理
const x = { foo: 'bar' };
const y = x;
y.foo = 'baz';
x === y; // true

// 使用 immutable.js

const SomeRecord = Immutable.Record({ foo: null });
const x = new SomeRecord({ foo: 'bar' });
const y = x.set('foo', 'baz');
x === y; // false

immutable.js

Immutable.js是解决这个问题的另一种方法。它通过结构共享提供不可突变的,持久的集合:

  • 不可突变:一旦创建,集合就不能在另一个时间点改变。

  • 持久性:可以使用原始集合和一个突变来创建新的集合。原始集合在新集合创建后仍然可用。

  • 结构共享:新集合尽可能多的使用原始集合的结构来创建,以便将复制操作降至最少从而提升性能。

rrreee

总结

PureComponent 真正起作用的,只是在一些纯展示组件上,复杂组件使用的话shallowEqual 那一关基本就过不了。另外在使用的过程中为了确保能够正确的渲染,记得 propsstaterrreee

PureComponent

Principle

コンポーネントが更新されるとき、コンポーネントの props と state が変更されていない場合、render メソッドはトリガーされず、パフォーマンス向上の目的を達成するための仮想 DOM の生成と比較プロセス。具体的には、React は自動的に浅い比較を行います:

rrreee そして、shallowEqual は何をするのでしょうか? Object.keys(state | props) の長さが一貫しているかどうか、各キーが両方を持っているかどうか、参照であるかどうかを比較します。つまり、最初のレベルの値のみが比較されますが、これは確かに非常に浅いものです。ネストが非常に深いため、データを比較できません。
問題

解決策🎜🎜 上記の問題からもわかるように、データが不変データの場合、参照を使用できます。ただし、可変データの場合、参照によって PureComponent に渡すことはできません。簡単に言うと、外側のレイヤーで PureComponent によって使用されるデータを変更するときは、再レンダリングできるように、そのデータに新しいオブジェクトまたは参照を割り当てる必要があります。たとえば、上記の例の handleClick を次のように変更して、正しいレンダリングを確認できます: 🎜rrreee🎜immutable.js🎜🎜Immutable.js は、この問題を解決するもう 1 つの方法です。構造共有を通じて、不変で耐久性のあるコレクションを提供します。 🎜
  • 🎜Immutable: コレクションは、一度作成されると、別の時点で変更できません。 🎜
  • 🎜永続性: 元のコレクションとミューテーションを使用して新しいコレクションを作成できます。元のコレクションは、新しいコレクションの作成後も引き続き使用できます。 🎜
  • 🎜構造の共有: コピー操作を最小限に抑え、パフォーマンスを向上させるために、新しいコレクションは元のコレクションの構造を可能な限り使用して作成されます。 🎜
rrreee🎜概要🎜🎜PureComponent は実際には一部の純粋な表示コンポーネントでのみ機能します。複雑なコンポーネントが使用されている場合、shallowEqual は基本的に取得できません。それを通して。さらに、使用中に正しいレンダリングを保証するために、propsstate は同じ参照を使用できないことに注意してください。 🎜🎜上記がこの記事の全内容です。その他の関連コンテンツについては、PHP 中国語 Web サイトをご覧ください。 🎜🎜関連する推奨事項: 🎜🎜🎜 AngularJs と Angular で一般的に使用される命令記述方法の違い🎜🎜🎜🎜🎜ztree は ajax を通じて json を取得し、小切手帳をチェックします🎜🎜🎜

以上がReact の PureComponent の概要の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。