Detaillierte Erklärung dieser Referenz in React

Detaillierte Erklärung dieser Referenz in React

Ich habe vor, ein Tagebuch zu schreiben, um die darauf hinweisenden Probleme in React aufzulisten. Der spezifische Prozess basiert auf den drei Elementen eines Ereignisses: Ursache, Prozess und Ergebnis. Hahahaha!

Ursache:

Wie wir alle wissen, ist React so konzipiert, dass es responsiv ist. Benutzer müssen weder das DOM noch die Daten manipulieren, und die Seite wird gerendert und aktualisiert.

Wenn die Daten aktualisiert werden, sobald sie sich ändern, bedeutet dies, dass der gesamte DOM aktualisiert wird? Natürlich nicht, rendern Sie neu, was sich geändert hat. Dann müssen wir den DOM vor und nach den Datenänderungen vergleichen. Direkt mit dem echten DOM vergleichen? Die Leistung wird sehr gering sein. React vergleicht virtuelles DOM, das ebenfalls ein Objekt ist, aber im Vergleich zum realen DOM hat es weniger Attribute und ist „leichter“.

Wie schreibe ich einen virtuellen DOM? In nativem JS können wir die Methode document.createElement() verwenden, um Knoten zu erstellen. React kann auch React.createElement(Komponente, Requisiten, untergeordnete Elemente) verwenden, aber diese Schreibmethode kann bei mehreren Verschachtelungsebenen verwirrend sein. So entstand JSX. JSX ist eigentlich der Syntaxzucker von React.createElement, aber es ist für uns bequemer zu verwenden. Wir können es direkt in der Form <p id="test">hallo</p> schreiben.

Aber das Problem tritt erneut auf! Die JSX-Syntax wird von webpack nicht erkannt. Standardmäßig kann webpack nur Dateien mit der Endung .js verarbeiten, daher müssen Sie den JavaScript-Compiler Babel verwenden, und bei Babel ist der strikte Modus aktiviert.

importiere React, {Komponente} von 'react'

exportiere Standardklassenindex erweitert Komponente {
    // sprechen(){
    // console.log(dies) // Ausgabe undefiniert
    // }
    speak = () => console.log(this) // Gib die Komponente render() aus {
        zurückkehren (
            <div>
                <button onClick={this.speak}>Schaltfläche</button>
            </div>
        )
    }
}

Dies bezieht sich im Wesentlichen auf seinen Aufrufer. Dies wird gebunden, wenn die Funktion ausgeführt wird. Gewöhnliche Funktionen in JS werden von window aufgerufen, daher zeigt es auf window. Nachdem der strikte Modus aktiviert wurde, ist es undefiniert.

(Funktion(){
    console.log(dieses) //Fenster
})()

Das in JSX übergebene Ereignis ist kein String (in nativem JS verwendet der Ereignislistener eine Rückruffunktion, während in Vue eine Stringvariable an das Listener-Ereignis übergeben wird), sondern eine Funktion (wie: onClick={this.speak} oben). In diesem Fall ist onClick eine Zwischenvariable und React ruft schließlich die Funktion auf. Da der strikte Modus aktiviert ist, ist dies nicht definiert, sodass der this-Zeiger in der Verarbeitungsfunktion verloren geht.

durchlaufen:

Tatsächlich benötigen wir lediglich einen Verweis auf das aktuell instanziierte Objekt, was das Schreiben des Codes zweifellos erheblich erleichtern würde. Es gibt zwei Stellen in der Klassenkomponente, an denen sich dies auf das aktuell instanziierte Objekt bezieht.

1. Konstruktor

Das „this“ im Konstruktor einer Klassenkomponente verweist auf das Instanzobjekt, was ein Feature von ES6-Klassen ist.

Wie wir alle wissen, verfügt Javascript nicht über das Klassenkonzept von C++ und JAVA. Die Implementierung der ES6-Klasse basiert ebenfalls auf einer Prototypenkette.

Vor ES6 sollte die Instanziierung eines Objekts folgendermaßen ablaufen:

Funktion Tier(Name, Alter) {
  dieser.name = Name
  this.age = Alter
}
Tier.prototyp.say = Funktion () {
  console.log(dieser.Name)
}
const Hund = neues Tier('Hund', 3)
Dog.say() //gibt „dog“ in der Konsole aus

Der neue Operator generiert zuerst ein leeres Objekt {}, erstellt dann einen this-Zeiger und zeigt damit auf das leere Objekt. Wenn der Konstruktor ausgeführt wird, entspricht dies dem dynamischen Hinzufügen von Eigenschaften zum Objekt, genau wie {}.name=dog,{}.age=3. Schließlich wird das generierte Objekt an Dog übergeben.

Wenn wir die obige Klasse mit der ES6-Klasse deklarieren, lautet der Code wie folgt:

Klasse Tier {
  Konstruktor(Name, Alter) {
    dieser.name = Name
    this.age = Alter
  }
  sagen() {
    console.log(dieser.Name)
  }
}
const Hund = neues Tier('Hund', 3)
Dog.say() //gibt „dog“ in der Konsole aus

Die Klassenimplementierung sollte ähnlich wie oben sein, es handelt sich also um das Instanzobjekt.

2. Renderfunktion

Dies bezieht sich in der Renderfunktion auch auf die Instanz. Warum?

Zunächst befindet sich die Rendermethode auf dem Prototyp der Klassenkomponente. Wenn React feststellt, dass die Komponente mithilfe einer Klasse definiert ist, erstellt es eine Instanz der Klasse. Beachten Sie, dass diese Instanz von React für Sie erstellt wird. Die Instanz ruft dann die Rendermethode auf, um den virtuellen DOM in den realen DOM umzuwandeln. Daher bezieht sich dies in Render auf die Instanz, schließlich wird es von ihr aufgerufen! In ähnlicher Weise ist „render“ ein Lebenszyklus-Hook, und dieser verweist in anderen Lebenszyklus-Hooks ebenfalls auf die Instanzkomponente.

3.Bind- und Pfeilfunktionen

Um dieses Problem zu lösen, benötigen wir zwei Wissensspeicher:

(1) binden
Call, Apply und Bind sind alle im Funktionsprototyp definiert, um den this-Zeiger der Funktion zu ändern. Der erste übergebene Parameter ist this, und die folgenden Parameter sind die Parameter von fun1.

Der Unterschied:

  • Call und Bind können mehrere Parameter an die aufgerufene Funktion übergeben, während Apply die Parameter in ein Array einfügt.
  • call und apply return Funktionen, die sofort ausgeführt werden, bind gibt eine neue Funktion zurück und bind()() wird ebenfalls sofort ausgeführt
  • Nachdem Sie Bind zum Binden verwendet haben, kann dies in der Funktion nicht mehr geändert werden, unabhängig davon, wer es aufruft
sei aa = {
    fun1: Funktion(a,b){
        console.log(dies)
        console.log(ab);
    }
}        
sei bb = {
    fun2: Funktion(a,b){
        console.log(dies)
        konsole.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) Pfeilfunktion: Die Pfeilfunktion erstellt keinen eigenen Ausführungskontext, daher ist das „this“ in der Pfeilfunktion das äußere „this“, und sie sucht Schicht für Schicht im äußeren Bereich nach diesem, bis eine Definition dafür vorhanden ist.

Konstante A = {
    Pfeil:() =>{
        console.log(dieses) //Fenster
    },
    Funktion:Funktion(){
        this.arrow()//Fenster
        console.log(dies) //A
        setzeTimeout(() => {
            console.log(dies) //A
        });
    }
}
Ein.Pfeil()
A.func()

Ergebnis:

Ich kenne zwei Lösungen, hehe!

Methode 1: Verwenden Sie Bind im Konstruktor

importiere React, {Komponente} von 'react'

exportiere Standardklassenindex erweitert Komponente {
    Konstruktor(){
        super()
        dies.sprechen = dies.sprechen.binden(dies)
        /*Löse das this-Problem in der Klasse: this.speak = this.speak.bind(this), das this im Konstruktor zeigt standardmäßig auf das Instanzobjekt,
      Das Instanzobjekt findet die fnc-Funktion im Prototyp der Klasse über die Prototypkette, ändert seinen this-Zeiger über die Bind-Funktion zum Instanzobjekt, gibt eine neue Funktion zurück, übergibt diese neue Funktion dann an die Instanz und nennt sie fnc*/
    }
    sprechen(){
        console.log(this) // Das aktuelle Instanzobjekt ausgeben}
    rendern() {
        zurückkehren (
            <div>
                <button onClick={this.speak}>Schaltfläche</button>
            </div>
        )
    }
}

Methode 2: Zuweisen von Pfeilfunktionen zu Klasseneigenschaften

importiere React, {Komponente} von 'react'

exportiere Standardklassenindex erweitert Komponente {
    sprechen = () => {
        console.log(dies)
    }
    rendern() {
        zurückkehren (
            <div>
                <button onClick={this.speak}>Schaltfläche</button>
            </div>
        )
    }
}//Wenn Sie Parameter übergeben müssen, können Sie die Idee des Funktionscurryings verwenden

Hinweis: Die Leistung variiert

Die Verwendung von Pfeilfunktionen zur Lösung dieses Problems ist weniger leistungsfähig, da Pfeilfunktionen keine Methoden, sondern anonyme Funktionsausdrücke sind. Die einzige Möglichkeit, sie einer Klasse hinzuzufügen, besteht darin, sie einer Eigenschaft zuzuweisen. Als wir zuvor ES6-Klassen vorgestellt haben, konnten wir sehen, dass ES-Klassen mit Methoden und Eigenschaften völlig anders umgehen.

Methoden werden dem Prototyp der Klasse hinzugefügt, anstatt einmal pro Instanz definiert zu werden.

Die Klassenattributsyntax ist syntaktischer Zucker für die Zuweisung derselben Attribute zu jeder Instanz und wird im Konstruktor tatsächlich folgendermaßen implementiert:

    Konstruktor(){
        super()
        dies.sprechen = () => {console.log(dies)}
    }

Dies bedeutet, dass Funktionen neu definiert werden, wenn neue Instanzen erstellt werden. Dadurch geht der Vorteil verloren, dass JS-Instanzen Prototypmethoden gemeinsam nutzen. Methode 1 fügt jedoch nur beim Generieren einer Instanz eine Bind-Operation hinzu, was große Vorteile hinsichtlich Effizienz und Speichernutzung bietet.

Oben finden Sie eine ausführliche Erklärung des this-Zeigers in React. Weitere Informationen zu diesem Zeiger in React finden Sie in den anderen verwandten Artikeln auf 123WORDPRESS.COM!

Das könnte Sie auch interessieren:
  • Detaillierte Erläuterung von drei Möglichkeiten zur Lösung des Bereichsproblems beim Binden und Übergeben von Parametern in React
  • Vier Lösungen für diesen Verlust in React
  • Beispielcode für bind(this) in der React-Komponente
  • 5 Möglichkeiten, dies in React.js zu binden (Zusammenfassung)
  • Detaillierte Erklärung von vier Möglichkeiten, dies an Ereignisse in React zu binden
  • Spezifische Verwendung von this in React-Komponenten
  • Achten Sie bei der Implementierung von reinem Render in React auf die versteckten Gefahren von „Bind(this)“!
  • Tiefgreifendes Verständnis der Methode zum Erstellen der Komponente this in es6 in React

<<:  So installieren Sie MySQL auf CentOS und richten den Fernzugriff ein

>>:  Einfache Schritte zum Erstellen eines MySQL-Containers mit Docker

Artikel empfehlen

Front-End-JavaScript-Funktionsprinzip

Inhaltsverzeichnis 1. Was ist eine JavaScript-Eng...

CSS-Menüschaltflächenanimation

Um ein Dropdown-Menü zu schreiben, klicken Sie au...

JS asynchroner Code Unit-Test Magie Promise

Inhaltsverzeichnis Vorwort Verkettung von Verspre...

Details zur Verwendung von „order by“ in MySQL

Inhaltsverzeichnis 1. Einleitung 2. Haupttext 2.1...

Lernen Sie, wie Sie in 6 Sekunden 1 Million Datensätze in MySQL einfügen

1. Idee Es dauerte nur 6 Sekunden, um 1.000.000 D...

MySQL lernen: Drei Paradigmen für Anfänger

Inhaltsverzeichnis 1. Paradigmenfundament 1.1 Der...

Mysql behält den vorhandenen Inhalt bei und fügt später Inhalte hinzu

Dieser Befehl ändert die Datentabelle ff_vod und ...

Wie viele Daten können in einer MySQL-Tabelle gespeichert werden?

Programmierer müssen sich viel mit MySQL befassen...

Tomcat erhält den Clientdomänennamen des Nginx-Reverse-Proxys

Frage Nach dem Nginx-Reverse-Proxy erhält die Tom...

So zeigen Sie den Speicherort von MySQL-Datendateien an

Wir haben möglicherweise eine Frage: Nachdem wir ...

Analyse des Unterschieds zwischen Emits und Attrs in Vue3

Inhaltsverzeichnis abschließend Praxisanalyse Erw...

Detaillierte Erläuterung der grundlegenden Docker-Netzwerkkonfiguration

Externer Zugriff Ports nach dem Zufallsprinzip zu...