Reactでのこのリファレンスの詳細な説明

Reactでのこのリファレンスの詳細な説明

React におけるこの指摘問題をリストアップする日記を書く予定です。具体的なプロセスは、イベントの 3 つの要素 (原因、プロセス、結果) に基づいています。ハハハハ!

原因:

ご存知のとおり、React はレスポンシブになるように設計されています。ユーザーは DOM やデータを操作する必要がなく、ページがレンダリングされ、更新されます。

データが変更された後に更新されると、DOM 全体が更新されることになりますか?もちろん、変更された部分を再レンダリングします。次に、データの変更前と変更後の DOM を比較する必要があります。実際のDOMと直接比較しますか?パフォーマンスは非常に低くなります。React は仮想 DOM を比較しますが、これもオブジェクトですが、実際の DOM と比較すると、属性が少なく、「軽量」です。

仮想DOMの書き方は?ネイティブ JS では、document.createElement() メソッドを使用してノードを作成できます。 React では React.createElement(component, props, children) も使用できますが、この記述方法は複数のネスト層に遭遇すると混乱を招く可能性があります。そこで JSX が誕生しました。JSX は実際には React.createElement のシンタックスシュガーですが、私たちにとってはより便利です。<p id="test">hello</p> の形式で直接記述できます。

しかし、問題は再び発生します。 JSX 構文は webpack では認識されません。デフォルトでは、webpack は .js サフィックスを持つファイルのみを処理できるため、JavaScript コンパイラ Babel を使用する必要があります。Babel では厳密モードが有効になっています。

React をインポートします。{ コンポーネント } を 'react' からインポートします。

エクスポートデフォルトクラスインデックスはComponentを拡張します{
    // 話す(){
    // console.log(this) // 出力は未定義
    // }
    話す = () => console.log(this) // コンポーネントを出力する render() {
        戻る (
            <div>
                <button onClick={this.speak}>ボタン</button>
            </div>
        )
    }
}

this は基本的に呼び出し元を参照します。関数の実行時にバインドされます。JS の通常の関数は window によって呼び出されるため、window を指します。厳密モードがオンになると、これは未定義になります。

(関数(){
    console.log(this) //ウィンドウ
})()

JSX で渡されるイベントは文字列ではなく (ネイティブ JS ではイベント リスナーがコールバック関数を使用しますが、Vue ではリスナー イベントに文字列変数が渡されます)、関数です (上記の onClick={this.speak} など)。この場合、onClick は中間変数であり、React は最終的に関数を呼び出します。厳密モードがオンになっているため、this は未定義となり、処理関数内の this ポインターは失われます。

以下を実行します:

実際、必要なのは、これが現在インスタンス化されているオブジェクトを指すことであり、これにより、コードの記述が間違いなく容易になります。クラス コンポーネントには、現在インスタンス化されているオブジェクトを参照する場所が 2 か所あります。

1. コンストラクター

クラス コンポーネントのコンストラクター内の this は、ES6 クラスの機能であるインスタンス オブジェクトを参照します。

ご存知のとおり、Javascript には C++ や JAVA のようなクラスの概念はありません。ES6 クラスの実装もプロトタイプ チェーンに基づいています。

ES6 より前では、オブジェクトのインスタンス化は次のようになります。

関数 Animal(名前, 年齢) {
  this.name = 名前
  this.age = 年齢
}
Animal.prototype.say = 関数 () {
  console.log(この名前)
}
const Dog = 新しい動物('dog', 3)
Dog.say() //コンソールにdogと表示されます

new 演算子は最初に空のオブジェクト {} を生成し、次に this ポインターを作成して空のオブジェクトを指します。コンストラクターが実行されると、{}.name=dog,{}.age=3 のように、オブジェクトにプロパティを動的に追加するのと同じになります。最後に、生成されたオブジェクトが Dog に渡されます。

ES6 クラスを使用して上記のクラスを宣言する場合、コードは次のようになります。

クラス動物{
  コンストラクタ(名前, 年齢) {
    this.name = 名前
    this.age = 年齢
  }
  言う() {
    console.log(この名前)
  }
}
const Dog = 新しい動物('dog', 3)
Dog.say() //コンソールにdogと表示されます

クラスの実装は上記と同様になるはずなので、this はインスタンス オブジェクトを参照します。

2.レンダリング機能

レンダリング関数内のこれもインスタンスを参照します。なぜ?

まず、render メソッドはクラス コンポーネントのプロトタイプにあります。React は、コンポーネントがクラスを使用して定義されていることを検出すると、そのクラスのインスタンスを作成します。このインスタンスは React によって作成されることに注意してください。次に、インスタンスは render メソッドを呼び出して仮想 DOM を実際の DOM に変換します。つまり、render 内の this はインスタンスを参照し、インスタンスによって呼び出されるのです。同様に、render はライフサイクル フックであり、他のライフサイクル フック内の this もインスタンス コンポーネントを指します。

3.bind関数とarrow関数

この問題を解決するには、2 つの知識ストアが必要です。

(1)縛る
call、apply、bind はすべて関数プロトタイプで定義され、関数の this ポインターを変更します。渡される最初のパラメーターは this であり、次のパラメーターは fun1 のパラメーターです。

違い:

  • Call と bind は呼び出された関数に複数のパラメータを渡すことができますが、apply はパラメータを配列に格納します。
  • callとapplyはすぐに実行される関数を返し、bindは新しい関数を返し、bind()()もすぐに実行されます。
  • bindを使用してこれをバインドした後は、誰が呼び出しても関数内のthisは変更できません。
aa = {とする
    fun1: 関数(a,b){
        console.log(これ)
        コンソールにログ出力します。
    }
}        
bb = {とする
    fun2: 関数(a,b){
        console.log(これ)
        コンソールログ(a+b);
    }
}

aa.fun1.call(bb,11,22);//bb-11
bb.fun2.apply(aa,[11,22]);//aa 33
aa.fun1.bind(bb,11,22)();//bb -11

(2)アロー関数:アロー関数は独自の実行コンテキストを作成しないので、アロー関数内のthisは外側のthisとなり、thisの定義が存在するまで外側のスコープ内で層ごとにthisを検索します。

定数A = {
    矢印:() =>{
        console.log(this) //ウィンドウ
    },
    関数:関数(){
        this.arrow()//ウィンドウ
        console.log(これ) //A
        タイムアウトを設定する(() => {
            console.log(これ) //A
        });
    }
}
A.矢印()
A.func()

結果:

解決策は2つ知っています、笑!

方法1: コンストラクターでbindを使用する

React をインポートします。{ コンポーネント } を 'react' からインポートします。

エクスポートデフォルトクラスインデックスはComponentを拡張します{
    コンストラクタ(){
        素晴らしい()
        this.speak = this.speak.bind(this)
        /*クラス内の this の問題を解決します: this.speak = this.speak.bind(this)、コンストラクタ内の this はデフォルトでインスタンスオブジェクトを指します。
      インスタンス オブジェクトは、プロトタイプ チェーンを通じてクラスのプロトタイプ上の fnc 関数を見つけ、bind 関数を通じてその this ポインタをインスタンス オブジェクトに変更し、新しい関数を返してから、この新しい関数をインスタンスに渡して fnc*/ という名前を付けます。
    }
    話す(){
        console.log(this) // 現在のインスタンスオブジェクトを出力します}
    与える() {
        戻る (
            <div>
                <button onClick={this.speak}>ボタン</button>
            </div>
        )
    }
}

方法2: クラスプロパティに矢印関数を割り当てる

React をインポートします。{ コンポーネント } を 'react' からインポートします。

エクスポートデフォルトクラスインデックスはComponentを拡張します{
    話す = () => {
        console.log(これ)
    }
    与える() {
        戻る (
            <div>
                <button onClick={this.speak}>ボタン</button>
            </div>
        )
    }
}//パラメータを渡す必要がある場合は、関数のカリー化という考え方を使うことができます

注: パフォーマンスは異なります

矢印関数はメソッドではなく匿名関数式であるため、この問題を解決するために矢印関数を使用するとパフォーマンスが低下します。そのため、矢印関数をクラスに追加する唯一の方法は、プロパティに割り当てることです。先ほど ES6 クラスを紹介したとき、ES クラスがメソッドとプロパティをまったく異なる方法で処理することがわかりました。

メソッドは、インスタンスごとに 1 回定義されるのではなく、クラスのプロトタイプに追加されます。

クラス属性構文は、各インスタンスに同じ属性を割り当てるための構文糖であり、実際には次のようにコンストラクターに実装されます。

    コンストラクタ(){
        素晴らしい()
        this.speak = () => {console.log(this)}
    }

つまり、新しいインスタンスが作成されるときに関数が再定義され、JS インスタンスがプロトタイプ メソッドを共有する利点が失われます。ただし、方法 1 では、インスタンスを生成するときにバインド操作のみが追加されるため、効率とメモリ使用量の点で大きな利点があります。

以上がReactにおけるthisポインターの詳しい説明です。Reactにおけるthisポインターについてさらに詳しく知りたい方は、123WORDPRESS.COM内の他の関連記事もぜひご覧ください!

以下もご興味があるかもしれません:
  • React で this をバインドしてパラメータを渡す際のスコープ問題を解決する 3 つの方法の詳細な説明
  • Reactでの損失に対する4つの解決策
  • Reactコンポーネントのbind(this)のサンプルコード
  • React.js でこれをバインドする 5 つの方法 (要約)
  • Reactでこれをイベントにバインドする4つの方法の詳細な説明
  • Reactコンポーネントでの具体的な使用法
  • react で pure render を実装するときは、bind(this) の隠れた危険性に注意してください。
  • Reactのes6でコンポーネントthisを作成する方法の詳細な理解

<<:  CentOS に MySQL をインストールしてリモート アクセスを設定する方法

>>:  DockerでMySQLコンテナを作成する簡単な手順

推薦する

Linux の高並列性とパフォーマンス最適化の落とし穴の紹介

目次序文Linux アプリケーション実行中に開いているファイルが多すぎる問題の分析と解決Linux ...

MySQL InnoDB のトランザクション特性を確保するにはどうすればよいですか?

序文「データベース トランザクションの特徴は何ですか?」と尋ねられたら、 ACID 特性である原子性...

Quickjs は JavaScript サンドボックスの詳細をカプセル化します

目次1. シナリオ2. 基盤となるAPIを簡素化する2.1 自動的に破棄を呼び出す2.2 VM値を作...

JS でページのスクリーンショット機能を実装する方法

「ページのスクリーンショット」は、ページポスターの生成、ポップアップ画像の共有など、フロントエンドで...

MySQL データ操作 - DML ステートメントの使用

例示するDML(データ操作言語)とは、データベースの追加、削除、変更を行うための操作命令のことです。...

JSは円形のプログレスバーのドラッグとスライドを実装します

この記事の例では、円形のプログレスバーのドラッグアンドスライドを実現するための具体的なJSコードを紹...

Linuxでawkを使用する方法の詳細な説明

awk を学ぶ前に、sed、grep、tr、cut などのコマンドを学んでおく必要があります。これら...

JavaScript の querySelector メソッドと getElementById メソッドの違いを分析する

目次1. 概要1.1 querySelector() と querySelectorAll() の使...

Mysql でよく使用される時間、日付、変換関数の概要

この記事では、主に実際のアプリケーションでよく使用されるMySQLの時刻と日付、および変換関数につい...

nginxリバースプロキシを介したデバッグコードの実装

背景現在、会社のプロジェクトは、フロントエンドとバックエンドが分離された方法で開発されています。新し...

JavaScript タイマー原理の詳細な説明

目次1. setTimeout() タイマー2. setTimeout() タイマーを停止する3. ...

Ubuntu 16.04 で Python 3 を使用して Django プロジェクトを作成し、実行する方法

ステップ1: Djangoプロジェクトを作成するターミナルを開き、書き込みたいプロジェクトのアドレス...

MySQL監視グループレプリケーションについて簡単に説明します

元のテキスト: https://dev.mysql.com/doc/refman/8.0/en/gr...

jsはカスタムドロップダウンボックスを実装します

この記事の例では、カスタムドロップダウンボックスを実装するためのjsの具体的なコードを参考までに共有...

MySQL explain クエリ命令情報の取得原理と例

explain はクエリ実行プラン情報を取得するために使用されます。 1. 文法次のように、sele...