ホームページ ウェブフロントエンド jsチュートリアル React コンポーネントのパフォーマンス最適化方法

React コンポーネントのパフォーマンス最適化方法

Mar 05, 2018 am 09:32 AM
react 最適化 方法

1. 単一の React コンポーネントのパフォーマンスの最適化

React はレンダリング パフォーマンスを向上させるために仮想 DOM を使用しますが、以前のレンダリング コンテンツがすべて破棄されるわけではありません。 Virtual DOM、DOM の助けを借りて、React は DOM ツリーへの最小限の変更を計算できます。これが React レンダリングの秘訣です。ただし、Virtual DOM は各 DOM の量を減らすことができます。仮想 DOM の計算と比較は最小限の処理であり、依然として複雑なプロセスです


もちろん、仮想 DOM の計算を開始する前にレンダリング結果が変わらないと判断できれば、実行する必要はありません。仮想 DOM の計算と比較が高速化されます。


2. shouldComponentUpdateのデフォルト実装


レンダリング結果が変わらないと判断した場合、仮想DOMの計算を開始する前にコンポーネントのレンダリングを防ぐことができるため、パフォーマンスが向上します。当然、 shouldComponentUpdate( nextProp, nextState) を使用することを考えます


shouldComponentUpdate 関数は、「いつ再レンダリングが必要ないか」を決定するために render 関数の前に呼び出されます。

は、更新を続行するかどうかを決定するためにブール値を返します。デフォルトで true を返します。 false が返された場合、更新は中断されます。


shouldComponentUpdate(nextProp,nextState){
  return (nextProp.completed !== this.props.completed) ||
    (nextProp.text !== this.props.text)
}
ログイン後にコピー

ここで、 nextProps は、このコンポーネントのレンダリング コンテンツに影響する唯一の props です。これら 2 つのプロパティが変更されていない限り、 shouldComponentUpdate は不要な更新を防ぐために false を返すことができます


ただし、型が基本型である場合、値が同じである限り、上記の比較は単なる「浅い比較」です。が同じである場合、「浅い比較」


も 2 つが同じであると見なされます:


次に、 prop の型が複合オブジェクトの場合はどうなるでしょうか?


複雑なオブジェクトの場合、「浅い比較」メソッドは 2 つのプロパティが同じオブジェクトへの参照であるかどうかのみをチェックします。そうでない場合は、オブジェクトの内容がまったく同じであっても、それらは 2 つの異なるプロパティとみなされます。次に、「詳細比較」を使用します。ただし、オブジェクトの構造は予測できません。各フィールドに対して「詳細比較」を再帰的に実行すると、コードが複雑になるだけでなく、パフォーマンスの問題が発生する可能性があります。


したがって、前後のオブジェクトタイプのプロパティが同じであることを確認したい場合は、そのプロパティが同じJavaScriptオブジェクトを指していることを確認する必要があります:


<Foo styleProp = {{color: "red"}}>
ログイン後にコピー

上記の受信メソッドの使用を避けるにはメソッドを使用する場合、レンダリングによって {color: "red"} オブジェクトが再作成されるたびに行う必要があり、参照アドレスは毎回異なり、そのため styleProp も毎回異なります。


const footStyle = {color: "red"};//确保这个初始化只执行一次,不要放在render函数中
<Foo styleProp = {footStyle}>
ログイン後にコピー

「シングルトンモード」を使用して、渡された styleProp が同じオブジェクトを指していることを確認してください


それが関数の場合はどうなるでしょうか?


<Foo onToggle={() => onToggleTodo(item.id)}/>
ログイン後にコピー

ここで割り当てられる値は匿名関数であり、割り当て中に生成されるため、上記の関数転送モードの使用は避けるべきです。つまり、これをレンダリングするたびに新しい関数が生成されることになります。問題の場所です。


渡される小道具がたくさんある場合はどうすればよいですか?


そうですね~~React-Redux を使用している場合は、 shouldComponentUpdate のデフォルト実装があります。


3. 複数の React コンポーネントのパフォーマンスの最適化


React コンポーネントがロード、更新、アンロードされると、コンポーネントの一連のライフサイクル関数が呼び出されます。ただし、これらのライフサイクル関数は特定の React コンポーネント関数用であり、アプリケーションでは多数の React コンポーネントが上から下まで結合されており、それらの間のレンダリング プロセスはより複雑になります。


同じコンポーネントのレンダリングプロセスでも、ロードフェーズ、更新フェーズ、アンロードフェーズの 3 つのプロセスを考慮する必要があります


ロードフェーズでは、コンポーネントはとにかく一度完全にレンダリングされ、そこからすべてのサブコンポーネントがレンダリングされる必要がありますReact コンポーネントを下向きに読み込む場合は、React コンポーネントの読み込みライフ サイクルを実行する必要があるため、行うべき最適化はあまりありません。


アンインストールフェーズには、componentWillUnmount というライフサイクル関数が 1 つだけあります。この関数は、componentDidMount およびその他の仕上げ作業によって追加されたイベント処理と監視のみをクリーンアップするため、最適化の余地はありません。 React 更新フェーズ (調整) プロセスで


コンポーネント更新プロセスでは、更新された仮想 DOM が構築され、以前の仮想 DOM と比較され、相違点が特定され、最小限の DOM 操作で更新されます

調整プロセス: つまり、React の更新中に Virtual DOM の違いを見つけるプロセスは、通常、N 個のノードを持つ 2 つのツリー構造を比較するアルゴリズムです。デフォルトの比較を直接使用し、ノード数が多すぎる場合、時間計算量は O(n*3) になります。必要な操作が多すぎるため、React がこのアルゴリズムを使用することは不可能です

React で実際に使用されるアルゴリズムの時間計算量は O(N) (時間計算量はアルゴリズムに必要な命令にすぎません)最良の場合と最悪の場合) 操作順序の推定)


ReactのReconciliationアルゴリズムは複雑ではありません。 まず、2つのツリー形状のルートノードの型が同じかどうかを確認します。同じか異なるか:


異なるノードタイプの場合

如果树形节点的类型不相同,那就意味着改动很大,直接认为原来的那个树形结构已经没用,可以扔掉,需要从新构建DOM树,原有的树形上的React组件便会经历“卸载”的生命周期;

也就是说,对于Virtual DOM树这是一个“更新”过程,但是却可能引发这个树结构上某些组件的“装载”和“卸载”过程
如:

更新前


 <p>
  <Todos />
 </p>
ログイン後にコピー

我们想要更新成这样:


 <span>
   <Todos />
 </span>
ログイン後にコピー

>1. 那么在作比较的时候,一看根节点原来是p,新的是span,类型就不一样了,那么这个算法就废弃之前的p包括里面的所有子节点,从新构建一个span节点和子节点;

>2. 很明显因为根节点不同就将所有的子节点从新构建,这很浪费,但是为了避免O(N*3)的时间复杂度,React这能选择这种比较简单、快捷的方法;

>3. 所以,作为开发者,我们一定要避免上面的浪费的情景出现

节点类型相同的情况

如果两个节点类型相同时,对于DOM元素,React会保留节点对应的DOM元素,只对其节点的属性和内容做对比,然后只修改更新的部分;

节点类型相同时,对于React组件类型,React做得是根据新节点的props去更新节点的组件实例,引发组件的更新过程;

在处理完根节点对比后,React的算法会对根节点的每一个子节点重复一样的操作

多个相同子组件的情况

如果最初组件状态为:


<ul>
  <TodoItem text = "First" />
  <TodoItem text = "Second" />

</ul>
ログイン後にコピー

更新后为:


<ul>
  <TodoItem text = "First" />
  <TodoItem text = "Second" />
  <TodoItem text = "Third" />
</ul>
ログイン後にコピー

那么React会创建一个新的TodoItem组件实例,而前两个则进行正常的更新过程但是,如果更新后为:


<ul>
  <TodoItem text = "Zero" />
  <TodoItem text = "First" />
  <TodoItem text = "Second" />

</ul>
ログイン後にコピー

(这将暴露一个问题)理想处理方式是,创建一个新的TodoItem组件实例放在第一位,后两个进入自然更新过程
但是要让react按照这种方式,就必须找两个子组件的不同之处,而现有计算两个序列差异的算法时间是O(N*2),显然则
不适合对性能要求很高的场景,所以React选择了一个看起来很傻的办法,即挨个比较每个子组件;

React首先认为把text为First的组件的text改为Zero,Second的改为First,最后创建一个text为Second的组件,这样便会破原有的两个组件完成一个更新过程,并创建一个text为Second的新组件

这显然是一个浪费,React也意到,并提供了方克服,不过需要开发人员提供一点帮助,这就是key

Key的使用

key属性可以明确的告诉React每个组件的唯一标识

如果最初组件状态为:


<ul>
  <TodoItem key={1} text = "First" />
  <TodoItem key={2} text = "Second" />

</ul>
ログイン後にコピー

更新后为:


<ul>
  <TodoItem key={0} text = "Zero" />
  <TodoItem key={1} text = "First" />
  <TodoItem key={2} text = "Second" />
</ul>
ログイン後にコピー

因为有唯一标识key,React可以根据key值,知道现在的第二和第三个组件就是之前的第一和第二个,便用原来的props启动更新过程,这样shouldComponentUpdate就会发生作用,避免无谓的更新;

注意:因为作为组件的唯一标识,所以key必须唯一,且不可变

下面的代码是错误的例子:


<ul>
  todos.map((item,index) => {
      <TodoItem
        key={index}
        text={item.text}
      />
    })
</ul>
ログイン後にコピー

使用数组下标作为key值,看起来唯一,但不稳定,因为随着todos数组值的不同,同样一个组件实例在不同的更新过程中数组的下标完全可能不同,把下标当做可以就会让React乱套,记住key不仅要唯一还要确保稳定不可变

需要注意:虽然key是一个prop,但是接受key的组件不能读取key的值,因为key和ref是React保留的两个特殊prop,并没有预期让组将直接访问。

相关推荐:

关于React组件项目实践

React组件性能优化方法解答

分解React组件的几种进阶方法

以上がReact コンポーネントのパフォーマンス最適化方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

トマト無料小説アプリで小説を書く方法. トマトノベルで小説を書く方法に関するチュートリアルを共有します。 トマト無料小説アプリで小説を書く方法. トマトノベルで小説を書く方法に関するチュートリアルを共有します。 Mar 28, 2024 pm 12:50 PM

トマト ノベルは非常に人気のある小説閲覧ソフトウェアです。トマト ノベルでは、新しい小説や漫画を読むことができます。どの小説も漫画もとても面白いです。小説を書きたい友達もたくさんいます。お小遣いを稼いで、小説の内容を編集することもできます。 「テキストに文章を書きたいです。それで、小説はどうやって書くのですか?友達は知らないので、一緒にこのサイトに行きましょう。小説の書き方の入門を少し見てみましょう。」 Tomato Novels を使用して小説を書く方法に関するチュートリアルを共有します。 1. まず、携帯電話で Tomato Free Novels アプリを開き、パーソナル センター - ライター センターをクリックします。 2. Tomato Writer Assistant ページに移動し、次の場所で [新しい本の作成] をクリックします。小説の終わり

WeChat で削除された連絡先を回復する方法 (簡単なチュートリアルでは、削除された連絡先を回復する方法について説明します) WeChat で削除された連絡先を回復する方法 (簡単なチュートリアルでは、削除された連絡先を回復する方法について説明します) May 01, 2024 pm 12:01 PM

残念ながら、WeChat は広く使用されているソーシャル ソフトウェアであり、何らかの理由で特定の連絡先を誤って削除してしまうことがよくあります。ユーザーがこの問題を解決できるように、この記事では、削除された連絡先を簡単な方法で取得する方法を紹介します。 1. WeChat の連絡先削除メカニズムを理解します。これにより、削除された連絡先を取得できるようになります。WeChat の連絡先削除メカニズムでは、連絡先がアドレス帳から削除されますが、完全には削除されません。 2. WeChat の組み込みの「連絡先帳復元」機能を使用します。WeChat には、この機能を通じて以前に削除した連絡先をすばやく復元できる「連絡先帳復元」機能が用意されています。 3. WeChat 設定ページに入り、右下隅をクリックし、WeChat アプリケーション「Me」を開き、右上隅にある設定アイコンをクリックして設定ページに入ります。

携帯電話の文字サイズの設定方法(携帯電話の文字サイズを簡単に調整できます) 携帯電話の文字サイズの設定方法(携帯電話の文字サイズを簡単に調整できます) May 07, 2024 pm 03:34 PM

携帯電話が人々の日常生活において重要なツールになるにつれて、フォント サイズの設定は重要なパーソナライゼーション要件になりました。さまざまなユーザーのニーズを満たすために、この記事では、簡単な操作で携帯電話の使用体験を向上させ、携帯電話のフォントサイズを調整する方法を紹介します。携帯電話のフォント サイズを調整する必要があるのはなぜですか - フォント サイズを調整すると、テキストがより鮮明で読みやすくなります - さまざまな年齢のユーザーの読書ニーズに適しています - フォント サイズを使用すると、視力の悪いユーザーにとって便利です携帯電話システムの設定機能 - システム設定インターフェイスに入る方法 - 設定インターフェイスで「表示」オプションを見つけて入力します。 - 「フォント サイズ」オプションを見つけて、サードパーティでフォント サイズを調整します。アプリケーション - フォント サイズの調整をサポートするアプリケーションをダウンロードしてインストールします - アプリケーションを開いて、関連する設定インターフェイスに入ります - 個人に応じて

モバイルドラゴンの卵を孵化させる秘密が明らかに(モバイルドラゴンの卵をうまく孵化させる方法を段階的に教えます) モバイルドラゴンの卵を孵化させる秘密が明らかに(モバイルドラゴンの卵をうまく孵化させる方法を段階的に教えます) May 04, 2024 pm 06:01 PM

テクノロジーの発展に伴い、モバイルゲームは人々の生活に欠かせないものになりました。かわいいドラゴンエッグの画像と面白い孵化過程で多くのプレイヤーの注目を集めており、その中でも注目を集めているゲームの一つがモバイル版ドラゴンエッグです。プレイヤーがゲーム内で自分のドラゴンをより適切に育成し成長させることができるように、この記事ではモバイル版でドラゴンの卵を孵化させる方法を紹介します。 1. 適切な種類のドラゴン エッグを選択する プレイヤーは、ゲーム内で提供されるさまざまな種類のドラゴン エッグの属性と能力に基づいて、自分に適したドラゴン エッグの種類を慎重に選択する必要があります。 2. 孵化機のレベルをアップグレードします。プレイヤーはタスクを完了し、小道具を収集することで孵化機のレベルを向上させる必要があります。孵化機のレベルは孵化速度と孵化成功率を決定します。 3. プレイヤーはゲームに参加する必要がある孵化に必要なリソースを収集します。

Go言語のメソッドと機能の違いと応用シナリオの分析 Go言語のメソッドと機能の違いと応用シナリオの分析 Apr 04, 2024 am 09:24 AM

Go 言語のメソッドと関数の違いは、構造との関連付けにあります。メソッドは構造に関連付けられ、構造データまたはメソッドを操作するために使用されます。関数は型に依存せず、一般的な操作を実行するために使用されます。

携帯電話の画面を保護する携帯電話のスクリーンプロテクターの選び方 (携帯電話のスクリーンプロテクターを購入する際のいくつかの重要なポイントとヒント) 携帯電話の画面を保護する携帯電話のスクリーンプロテクターの選び方 (携帯電話のスクリーンプロテクターを購入する際のいくつかの重要なポイントとヒント) May 07, 2024 pm 05:55 PM

スマートフォンの普及に伴い、携帯フィルムは欠かせないアクセサリーの一つとなりました。耐用年数を延ばすには、携帯電話の画面を保護する適切な携帯電話フィルムを選択してください。この記事では、読者が自分に最適な携帯電話フィルムを選択できるように、携帯電話フィルムを購入する際のいくつかのポイントとテクニックを紹介します。携帯電話フィルムの素材と種類を理解する:PET フィルム、TPU など。 携帯電話フィルムは強化ガラスを含むさまざまな素材でできています。 PETフィルムは比較的柔らかく、強化ガラスフィルムは耐傷性に優れ、TPUは耐衝撃性能に優れています。選択する際は、個人の好みやニーズに基づいて決定できます。画面の保護の程度を考慮してください。携帯電話のフィルムの種類によって、画面の保護の程度も異なります。 PETフィルムは主に傷防止の役割を果たしますが、強化ガラスフィルムは落下耐性に優れています。より良いものを選ぶことができます

Java フレームワークとフロントエンド React フレームワークの統合 Java フレームワークとフロントエンド React フレームワークの統合 Jun 01, 2024 pm 03:16 PM

Java フレームワークと React フレームワークの統合: 手順: バックエンド Java フレームワークをセットアップします。プロジェクト構造を作成します。ビルドツールを設定します。 React アプリケーションを作成します。 REST API エンドポイントを作成します。通信メカニズムを構成します。実際のケース (SpringBoot+React): Java コード: RESTfulAPI コントローラーを定義します。 React コード: API によって返されたデータを取得して表示します。

C++ プログラムの最適化: 時間の複雑さを軽減する手法 C++ プログラムの最適化: 時間の複雑さを軽減する手法 Jun 01, 2024 am 11:19 AM

時間計算量は、入力のサイズに対するアルゴリズムの実行時間を測定します。 C++ プログラムの時間の複雑さを軽減するためのヒントには、適切なコンテナー (ベクター、リストなど) を選択して、データのストレージと管理を最適化することが含まれます。クイックソートなどの効率的なアルゴリズムを利用して計算時間を短縮します。複数の操作を排除して二重カウントを削減します。条件分岐を使用して、不必要な計算を回避します。二分探索などのより高速なアルゴリズムを使用して線形探索を最適化します。

See all articles