TypeScript-Dekorator-Definition

TypeScript-Dekorator-Definition

Vorwort:

Decorator wurde in ECMAScript vorgeschlagen, ist aber noch nicht fertiggestellt; er wurde in TypeScript implementiert, ist aber noch eine experimentelle Funktion. Wenn Sie den Dekorator verwenden möchten, müssen Sie experimentalDecorators in tsconfig.json auf true setzen.

1. Konzept

1.1 Definition

Ein Dekorator ist ein neuer Deklarationstyp, der auf Klassendeklarationen, Methoden, Zugriffsmethoden, Eigenschaften und Parameter angewendet werden kann. Der Dekorator wird mit dem @-Symbol und einem Funktionsnamen verwendet, z. B. @testDecorator , wobei testDecorator eine Funktion sein oder eine Funktion zurückgeben muss. Diese Funktion wird zur Laufzeit aufgerufen und die dekorierte Anweisung wird automatisch als Parameter übergeben.

Es ist zu beachten, dass der Dekorator unmittelbar vor dem zu ändernden Inhalt platziert werden sollte und dass nicht alle Dekoratoren in Deklarationsdateien.d.ts. und jedem externen Kontext (wie z. B. declare ) verwendet werden können.

Die Definition und Verwendung des Dekorators sind wie folgt:

//Definieren Sie eine Funktion als Dekorationsfunktion, um die Funktion testDecorator() {} zu verwenden.

//Verwenden Sie den Dekorator @testDecorator über das @-Symbol

1.2 Dekorateurfabrik

Die sogenannte Dekoratorfabrik ist ebenfalls eine Funktion. Der Unterschied zur normalen Dekoratorfunktion besteht darin, dass ihr Rückgabewert eine Funktion ist und die zurückgegebene Funktion als vom Dekorator aufgerufene Funktion verwendet wird. Wenn Sie eine Dekorationsfabrik verwenden, können Sie bei der Verwendung je nach aktueller Nutzung unterschiedliche Parameter übergeben. Bei der Verwendung müssen Sie jedoch einen Funktionsaufruf hinzufügen.

Der Beispielcode lautet wie folgt:

// Decorator-Factory, der Rückgabewert ist eine Funktion function testDecorator() {
    Rückgabefunktion () {}
}

//Verwende den Dekorator @testDecorator() durch @symbol + Funktionsaufruf

1.3 Dekorateur-Kombination

Dekoratoren können in Kombination verwendet werden, das heißt, Sie können ein Ziel verwenden und auf mehrere Dekoratoren verweisen.

Der Beispielcode lautet wie folgt:

// Definieren Sie zwei Dekoratorfunktionen function setName() {}
Funktion setzeAlter() {}

//Dekorator @setName verwenden
@setAge
Klasse Person {}

Wenn mehrere Dekoratoren verwendet werden, werden die Dekoratoren der Reihe nach ausgeführt und die Ausführungsreihenfolge ist wie folgt:

Wenn eine normale Dekoratorfunktion verwendet wird, erfolgt die Ausführungsreihenfolge von unten nach oben.

Der Beispielcode lautet wie folgt:

Funktion setName(Konstruktor: beliebig) {
  console.log('setName', Konstruktor)
}
Funktion setAge(Konstruktor: beliebig) {
  console.log('setAge', Konstruktor)
}
@Name festlegen
@setAge
Klasse Person {}
/* Die Ausführungsergebnisse sind wie folgt:
setAge [Funktion: Person]
setName [Funktion: Person]
*/


Wenn es sich um eine Dekorationsfabrik handelt, besteht ihre Ausführungsreihenfolge darin, die Fabrikfunktion von oben nach unten auszuführen und dann die von der Fabrikfunktion zurückgegebene Funktion von unten nach oben auszuführen. Der Beispielcode lautet wie folgt

Funktion setzeName() {
  console.log('setName abrufen')
  return Funktion (Konstruktor: beliebig) {
    console.log('setName', Konstruktor)
  }
}
Funktion setzeAlter() {
  console.log('Alter festlegen')
  return Funktion (Konstruktor: beliebig) {
    console.log('setAge', Konstruktor)
  }
}
@setName()
@setAge()
Klasse Person {}
/* Die Ausführungsergebnisse sind wie folgt:
setName abrufen
SetAge abrufen
setAge [Funktion: Person]
setName [Funktion: Person]
*/

1.4 Dekorateur-Bewertung

Dekoratoren auf verschiedene Deklarationen in einer Klassendefinition werden in der unten angegebenen Reihenfolge angewendet:

  • Auf jedes Instanzmitglied wird ein Parameter-, Methoden-, Accessor- oder Eigenschaften-Dekorator angewendet.
  • Auf jedes statische Mitglied wird ein Parameter-, Methoden-, Accessor- oder Eigenschaften-Dekorator angewendet.
  • Der Parameter-Dekorator wird auf den Konstruktor angewendet;
  • Klassendekoratoren werden auf Klassen angewendet.

2. Klassendekorateur

Klassendekoratoren werden vor Klassendeklarationen verwendet und müssen unmittelbar vor dem zu dekorierenden Inhalt platziert werden. Klassendekoratoren werden auf Klassendeklarationen angewendet.

Der Klassendekoratorausdruck wird zur Laufzeit als Funktion aufgerufen und hat einen Parameter, der der Konstruktor dieser Klasse ist.

Der Beispielcode lautet wie folgt:

let sign = null
Funktion setzeName() {
  return-Funktion (Konstruktor: Funktion) {
    Zeichen = Konstruktor
  }
}
@setName()
Klasseninfo {
  Konstruktor() {}
}
console.log(Zeichen === Info) // wahr
Konsole.log(Zeichen === Info.Prototyp.Konstruktor) // wahr

Aus dem obigen Code können wir erkennen, dass constructor Konstruktoreigenschaft des Prototypobjekts der Klasse Info tatsächlich auf Info selbst verweist.

Wir können auch Dekoratoren verwenden, um das Prototypobjekt und den Konstruktor einer Klasse zu ändern. Der Beispielcode lautet wie folgt:

// * Ändern Sie das Prototypobjekt und die Konstruktorfunktion addName(constructor: { new (): any }) {
  constructor.prototype.name = "Eine Schüssel Zhou"
}
@Name hinzufügen
Klasse Person {}
const person = neue Person()
console.log(person.name) // Fehler: Eigenschaft „name“ existiert beim Typ „A“ nicht

Im obigen Code verwenden wir den Modifikator addName , um dem Prototyp der Klasse Person ein Namensattribut hinzuzufügen, sodass von der Klasse Person instantiierte Objekte auf das Namensattribut zugreifen können. Dies ist jedoch tatsächlich nicht der Fall. Hier wurde eine Ausnahme ausgelöst. Um dieses Problem zu lösen, können Sie Typbehauptungen verwenden oder eine Schnittstelle mit demselben Namen definieren und diese durch Zusammenführen deklarieren.

Der Beispielcode lautet wie folgt:

Funktion addName(Konstruktor: { neu (): beliebig }) {
  constructor.prototype.name = "Eine Schüssel Zhou"
}
@Name hinzufügen
Klasse Person {}
const person = neue Person()
// 1. Typbehauptung // console.log((person as any).name) // Zurück // 2. Definieren Sie eine Schnittstelle mit dem gleichen Namen und deklarieren Sie eine Zusammenführungsschnittstelle Person {
  Name: Zeichenfolge
}

console.log(Person.Name) // Yiwan Zhou

Und wir können den Konstruktor auch durch den Dekorator überladen. Der Beispielcode lautet wie folgt:

// * Überlade die Konstruktorfunktion classDecorator<T extends { new (...args: any[]): {} }>(
  Konstruktor: T,
) {
  return Klasse erweitert Konstruktor {
    Name = „Eine Schüssel Zhou“
    Hobby = "Programmieren"
  }
}
@classDecorator
Klasse Person {
  Alter = 18
  Name: Zeichenfolge
  Konstruktor(Name: Zeichenfolge) {
    dieser.name = Name
  }
}
const person = neue Person('Yiwan Zhou')
console.log(Person)
/* Die Ausführungsergebnisse sind wie folgt:
{
  Alter: 18,
  Name: 'Eine Schale Zhou',
  Hobby: 'Programmieren',
}
*/

Wir können Parameter auch über die Dekorator-Factory übergeben. Der Beispielcode lautet wie folgt:

//Definieren Sie eine Dekorator-Factory-Funktion classDecorator(_name: string) {
  Rückgabefunktion <T erweitert { neu (...args: any[]): {} }>(Konstruktor: T) {
    return Klasse erweitert Konstruktor {
      Name = _Name
      Hobby = "Programmieren"
    }
  }
}
@classDecorator('Eine Schüssel Zhou')
Klasse Person {
  Alter = 18
  Name: Zeichenfolge
  Konstruktor(Name: Zeichenfolge) {
    dieser.name = Name
  }
}
const person = new Person('eine Schüssel Haferbrei')
console.log(Person)
/* Die Ausführungsergebnisse sind wie folgt:
{
  Alter: 18,
  Name: 'Eine Schale Zhou',
  Hobby: 'Programmieren',
}
*/

3. Methodendekorator

Der Methodendekorator wird zum Verarbeiten der Methoden in der Klasse verwendet. Er kann den Eigenschaftsdeskriptor der Methode (Informationen zum Eigenschaftsdeskriptor finden Sie unter Object.defineProperty ()) und die Methodendefinition verarbeiten. Die Methode Decorator wird zur Laufzeit ebenfalls als Funktion aufgerufen, die drei Parameter enthält.

Die Einzelheiten lauten wie folgt:

Bei statischen Mitgliedern ist es der Klassenkonstruktor, bei Instanzmitgliedern ist es das Prototypobjekt der Klasse.

Der Vorname des Mitglieds.

Der Eigenschaftendeskriptor des Mitglieds.

Beachten Sie, dass der Eigenschaftsdeskriptor undefined ist, wenn die Codeausgabe auf eine Version niedriger als ES5 abzielt.

Der folgende Code definiert einen einfachen Methodendekorator durch die Dekoratorfabrik. Der Beispielcode lautet wie folgt:

// Dekorator-Fabrikfunktion enumerable(bool: boolean) {
  /**
   * Der Methodendekorator akzeptiert drei Parameter:
   * 1. target: für statische Mitglieder ist es der Konstruktor der Klasse; für Instanzmitglieder ist es das Prototypobjekt der Klasse* 2. propertyName: der Name des Mitglieds* 3. descriptor: Eigenschaftsdeskriptor, sein Typ ist PropertyDescriptor
   */
  return-Funktion (
    Ziel: beliebig,
    Eigenschaftsname: Zeichenfolge,
    Deskriptor: PropertyDescriptor,
  ) {
    //Bestimmen Sie, ob die Methode aufzählbar ist, basierend auf dem übergebenen Bool-Deskriptor.enumerable = bool
  }
}
Klasseninfo {
  Konstruktor (öffentlicher Name: Zeichenfolge) {}
  @enumerable(falsch)
  getName() {
    gib diesen Namen zurück
  }
}
const info = neue Info('Eine Schüssel Zhou')
// Beim direkten Drucken enthält das Objekt die Methode getName() nicht, da die Methode nicht aufzählbar ist.
console.log(info) // { name: "Yiwan Zhou" }
// Aber Sie können diese Methode console.log(info.getName()) aufrufen. // Yiwan Zhou

Im obigen Code haben wir den Eigenschaftsdeskriptor der Methode in der Klasse direkt über den Dekorator geändert.

Wenn der Methodendekorator einen Wert zurückgibt, wird dieser Wert als Eigenschaftsdeskriptorobjekt der Methode verwendet. Der Beispielcode lautet wie folgt:

// Dekorator-Fabrikfunktion enumerable(bool: boolean) {
  return-Funktion (
    Ziel: beliebig,
    Eigenschaftsname: Zeichenfolge,
    Deskriptor: PropertyDescriptor,
  ) {
    zurückkehren {
      Wert: Funktion () {
        return 'Fehler: Name ist nicht definiert'
      },
      aufzählbar: bool,
    }
  }
}
Klasseninfo {
  Konstruktor (öffentlicher Name: Zeichenfolge) {}
  @enumerable(falsch)
  getName() {
    gib diesen Namen zurück
  }
}
const info = neue Info('Eine Schüssel Zhou')
console.log(info) // { name: "Yiwan Zhou" }
console.log(info.getName()) // Fehler: Name ist nicht definiert

Im obigen Code gibt unser Methodendekorator ein Objekt zurück, dessen Werteigenschaft die Methodendefinition ändert, sodass das Endergebnis Error: name is undefined ist.

4. Accessoire-Dekorateur

Der Accessor-Decorator besteht aus set und get -Methoden, die wir zuvor gelernt haben. Eine wird beim Festlegen des Eigenschaftswerts und die andere beim Abrufen des Eigenschaftswerts ausgelöst.

Der Accessor-Decorator akzeptiert genau wie der Methoden-Decorator drei Parameter, daher werde ich hier nicht ins Detail gehen.

Der Beispielcode lautet wie folgt:

Funktion aufzählbar(bool: boolean) {
  return-Funktion (
    Ziel: beliebig,
    Eigenschaftsname: Zeichenfolge,
    Deskriptor: PropertyDescriptor,
  ) {
    Deskriptor.aufzählbar = bool
  }
}
Klasseninfo {
  private_name: Zeichenfolge
  Konstruktor(Name: Zeichenfolge) {
    dieser._name = Name
  }
  @enumerable(falsch)
  Name abrufen() {
    gib dies zurück._name
  }
  setze Namen(Name) {
    dieser._name = Name
  }
}

Es ist erwähnenswert, dass es in TypeScript nicht zulässig ist, sowohl get als auch set Accessoren eines Mitglieds zu dekorieren.

5. Immobiliendekorateur

Der Eigenschaftendekorator wird vor der Eigenschaftendeklaration deklariert und verfügt über zwei Parameter, wie unten gezeigt:

  • Bei statischen Mitgliedern ist es der Klassenkonstruktor, bei Instanzmitgliedern ist es das Prototypobjekt der Klasse.
  • Der Vorname des Mitglieds.

Der Beispielcode lautet wie folgt:

Funktion printPropertyName(Ziel: beliebig, propertyName: Zeichenfolge) {
  console.log(Eigenschaftsname)
}
Klasseninfo {
  @printPropertyName
  Name: Zeichenfolge
  @printPropertyName
  Alter: Anzahl
  Konstruktor(Name: Zeichenfolge, Alter: Zahl) {
    dieser.name = Name
    this.age = Alter
  }
}
neue Info('Yiwan Zhou', 18)

Die Ausführungsergebnisse sind wie folgt:

Name
Alter

6. Parameter-Dekorator

Der Parameterdekorator hat die folgenden drei Parameter:

  • Bei statischen Mitgliedern ist es der Klassenkonstruktor, bei Instanzmitgliedern ist es das Prototypobjekt der Klasse.
  • Der Vorname des Mitglieds.
  • Der Index des Parameters in der Parameterliste der Funktion.

Die Funktion des Parameter-Dekorators besteht darin, zu überwachen, ob ein Methodenparameter übergeben wird. Der Rückgabewert des Parameter-Dekorators wird ignoriert.

Der Beispielcode lautet wie folgt:

Funktion erforderlich (Ziel: beliebig, Eigenschaftsname: Zeichenfolge, Index: Zahl) {
  console.log(`Der geänderte Parameter ist der ${index + 1}te Parameter von ${propertyName}`)
}
Klasseninfo {
  Name: Zeichenfolge = „Eine Schüssel Zhou“
  Alter: Zahl = 18
  getInfo(Präfix: Zeichenfolge, @erforderlicher Infotyp: Zeichenfolge): beliebig {
    Rückgabepräfix + ' ' + this[infoType]
  }
}
Schnittstelleninfo {
  [Schlüssel: Zeichenfolge]: Zeichenfolge | Zahl | Funktion
}
const info = neue Info()
info.getInfo('', 'age') // Ändert den zweiten Parameter von getInfo

Hier verwenden wir den Parameter-Decorator vor dem zweiten Parameter getInfo -Methode, damit wir einige Informationen im Decorator erhalten können.

Dies ist das Ende dieses Artikels über TypeScript-Dekoratordefinitionen. Weitere Informationen zu TypeScript-Dekoratoren finden Sie in den vorherigen Artikeln von 123WORDPRESS.COM oder in den folgenden verwandten Artikeln. Ich hoffe, Sie werden 123WORDPRESS.COM auch in Zukunft unterstützen!

Das könnte Sie auch interessieren:
  • Eine kurze Erläuterung, wie man die Error-Klasse in TypeScript erbt
  • Detaillierte Erklärung der privaten Klassenfelder von JavaScript und der privaten Modifizierungen von TypeScript
  • Fallbeispiel zur TypeScript-Schnittstellendefinition
  • Tutorial zur TypeScript-Funktionsdefinition und zu Anwendungsfällen
  • TypeScript-Lernhinweise: TypeScript-Klassendefinition, Klassenvererbung, Klassenmitgliedsmodifikatoren

<<:  Details zu MySQL-Zeittypen und -Modi

>>:  Implementierung der gleichmäßigen Aufteilung des übergeordneten Containers (perfekte Drittel) in CSS

Artikel empfehlen

HTML-Tbody-Verwendung

Strukturierte Tabelle (nur IExplore) 1) Gruppieren...

MySQL verwendet UNIQUE, um das Einfügen nicht doppelter Daten zu implementieren

SQL UNIQUE-Einschränkung Die UNIQUE-Einschränkung...

Analyse des MySQL-Sperrmechanismus und der Verwendung

Dieser Artikel veranschaulicht anhand von Beispie...

Docker-Verbindung – MongoDB-Implementierungsprozess und Codebeispiele

Nachdem der Container gestartet wurde Melden Sie ...

Das WeChat-Applet realisiert die Funktion zum Hochladen von Bildern

In diesem Artikelbeispiel wird der spezifische Co...

Detaillierte Erklärung des Lebenszyklus einer Angular-Komponente (I)

Inhaltsverzeichnis Überblick 1. Hook-Aufrufreihen...

JavaScript ist unzuverlässig undefiniert

undefined Wenn wir in JavaScript feststellen möch...

Der Unterschied zwischen Vue-Interpolationsausdruck und V-Text-Direktive

Inhaltsverzeichnis 1. Verwenden Sie Plugin-Ausdrü...

JavaScript-Grundlagen: Fehlererfassungsmechanismus

Inhaltsverzeichnis Vorwort Error-Objekt werfen ve...

So stellen Sie verschiedene Mausformen dar

<a href = "http: //" style = "c...

Webdesign-Tutorial (3): Designschritte und Denkweise

<br />Vorheriges Tutorial: Webdesign-Tutoria...