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コンテナを作成する簡単な手順

推薦する

Mac OS に MySQL 5.7.20 をインストールするための詳細なグラフィックとテキストの説明

Mac OS X で TAR.GZ から MySQL 5.7 をインストールする MySQL 5.6...

Docker で MySQL マスター スレーブ レプリケーションを実装するためのサンプル コード

目次1. 概要1. 原則2. 実装3. スレーブインスタンスを作成する4. マスタースレーブ構成要約...

Linuxコマンドをバックグラウンドで実行する方法

通常、ターミナルでコマンドを実行する場合、別のコマンドの入力を開始する前に、現在のコマンドが終了する...

マークアップ言語 - リスト再び

123WORDPRESS.COM HTML チュートリアル セクションに戻るには、ここをクリックして...

MySQL パフォーマンスの包括的な最適化方法リファレンス、CPU、ファイルシステムの選択から mysql.cnf パラメータの最適化まで

この記事では、一般的な MySQL 最適化方法をいくつかまとめて簡単に紹介します。これは、フルタイム...

ドラミング効果を実現するJavascript

この記事では、ドラミング効果を実現するためのJavascriptの具体的なコードを参考までに紹介しま...

mysql 8.0.16 winx64 および Linux でルート ユーザーのパスワードを変更する方法

データベースへの接続などの基本的な操作はご自身で行ってください。この記事ではパスワードの変更方法を中...

LeetCode の SQL 実装 (182. 重複するメールボックス)

[LeetCode] 182.重複メールPerson という名前のテーブル内のすべての重複メールを...

Docker を使用した ELK7.3.0 ログ収集サービスの導入に関するベスト プラクティス

最初に書くこの記事では、ELK 7.3.0 の展開についてのみ説明します。展開環境:システムセントO...

503 サービス利用不可エラーの解決方法の説明

1. Webページを開くと503サービス利用不可が表示されますが、更新すると正常にアクセスできます。...

Dockerイメージのローカル移行の実装

最近 Docker を勉強しているのですが、よく問題に遭遇します。Docker イメージをダウンロー...

証明書を使用してリモート Docker サーバーに接続する方法

目次1. スクリプトを使用してDockerのTLSを暗号化する2. Dockerの設定を変更してリモ...

不規則な投影を実現するためのボックスシャドウとドロップシャドウのサンプルコード

border-radius で生成できる四角形やその他の図形に影を追加する場合 (「Adaptive...

Mysql関数呼び出しの最適化の詳細な説明

目次関数呼び出しの最適化関数呼び出しの最適化MySQL 関数は、内部的に決定論的または非決定論的とし...

Ubuntu 18.04 で apt-get ソースを変更する方法

apt-get を使用してインストールすると、非常に遅くなります。国内のソースを変更すると、この問題...