LWC-Klassendefinitionssyntax (Lightning Web Component)
Lightning Web Components (LWC) bestehen aus mehreren Dateien in einem Bundle. Bei dieser Frage konzentriere ich mich auf die Haupt-JS-Datei der Komponente, in der die JS-Klasse der Webkomponente implementiert ist.
Beispielcode:
import { LightningElement, api } from 'lwc';
import { NavigationMixin } from 'lightning/navigation';
import doSomething from '@salesforce/apex/MyApexClass.doSomething';
export default class MyLWC extends NavigationMixin(LightningElement) {
@api a;
@api b;
download() {
let that = this;
doSomething({
param1: this.a,
param2: this.b
})
.then((result) => {
that.navigateToWebPage(result);
})
.catch((error) =>{
console.log(`Error occured ${error}`);
});
}
navigateToWebPage(url) {
// Navigate to a URL
this[NavigationMixin.Navigate]({
type: 'standard__webPage',
attributes: {
url: url
}
},
false // Replaces the current page in your browser history with the URL
);
}
}
Es gibt zwei Dinge, die ich hier nicht verstehe:
extends NavigationMixin(LightningElement)Syntax - warum Klammern? Können js-Klassen mehr als eine übergeordnete Klasse erweitern?this[NavigationMixin.Navigate]- Nach dem Code zu urteilen, scheint es, als hätte'this'die Navigate-Funktion (und möglicherweise andere Funktionen von NavigateMixin?) Dem Prototyp zugewiesen. Warum verwenden wir NavigationMixin nicht wie jede andere importierte Komponente - rufen ihre Funktionen nur direkt auf, nicht überthis?
Kann jemand erklären, was tatsächlich passiert, wenn diese Art von Klassenerweiterungen / Vererbung verwendet wird und ob die hier verwendete Syntax etwas Standard aus der Welt der Webkomponenten oder etwas Spezifisches für LWC ist?
Danke für deine Antworten!
Antworten
Die Navigations-API verwendet JavaScript-Mixins!
Mixin - ist ein allgemeiner objektorientierter Programmierbegriff: eine Klasse, die Methoden für andere Klassen enthält. Einige andere Sprachen erlauben Mehrfachvererbung. JavaScript unterstützt keine Mehrfachvererbung, aber Mixins können durch Kopieren von Methoden in den Prototyp implementiert werden.
Lesen Sie mehr über Mixins hier und mehr über Klasse basiert Mixins hier
Ich habe mich immer danach gefragt, wie schwierig die Syntax ist und warum das lwc-Team Mixin nur für die Navigation gewählt hat. Es scheint von der Komposition abzuweichen und in diesem Fall wird die Vererbung der Komposition vorgezogen!
Die Antwort des LWC-Plattformteams - LNS (Lightning Navigation Service) hat es auf seiner Roadmap, sich aufgrund des inkonsistenten Erscheinungsbilds vom Mixin zu entfernen.
Die Hauptqualität der Navigations-API, die zu etwas anderem geführt hat, besteht darin, dass es sich um eine kontextbezogene API handelt, die wie ein Ereignis behandelt werden sollte. Wir entscheiden uns jedoch dafür, sie eher wie eine herkömmliche JS / Funktions-API zu verwenden, um die Abhängigkeit von Ereignissen zu vermeiden und dies möglich zu machen zukünftige statische Analysierbarkeit, die man mit Ereignissen nicht bekommen konnte.
Es gibt eine Roadmap, um die Ausrichtung auf einzelne Importe zu verbessern, anstatt eine Mixin-Klasse zu erstellen
Mixins können grundsätzlich einige Elemente zum Prototyp einer Klasse zusammenführen. Für ein kurzes Beispiel:
class Animal {
constructor(family) { this.family = family; }
makeSound() { console.log('Animal of the ' + this.family + ' family making a sound.'); }
}
const StickCatcher = (superclass) => class extends superclass {
catchStick() { console.log('Entity of the ' + this.family + ' family catching a stick.'); }
}
class Dog extends StickCatcher(Animal) {
constructor(dogName) {
super('canine'); // the super() "routes" to Animal (not to the StickCatcher)
this.dogName = dogName;
}
wagTail() { console.log(this.dogName + ' wags his tail.'); }
}
const fido = new Dog('Fido');
fido.makeSound(); // Animal of the canine family making a sound
fido.catchStick(); // Entity of the canine family catching a stick
fido.wagTail(); // Fido wags his tail
Der StickCatcher ist ein MixIn; Es ist eine "Klassenfabrik", die eine Klasse zurückgibt, die mit einigen Funktionen "angereichert" wurde - in diesem Fall mit einer catchStick()Funktion. Dem StickCatcher ist es egal, welche Klasse er erweitern möchte. ( catchStick()würde sich aber darum kümmern, dass es darin this.familyexistiert).
Beachten Sie andererseits, dass die Superklasse des Hundes Tier ist. StickCatcher ist keine Klasse , sondern eine Funktion , die Klassen zurückgibt, dh eine "Klassenfactory". Das super('canine')wird somit dem Tierkonstrukteur zugeführt. Das Ergebnis ist ein Hund, der alle Elemente von Animal und StickCatcher enthält (natürlich neben denen von Dog) - dh die StickCatcher-Methoden wurden in die Klassenhierarchie von Tier zu Hund gemischt .
Was ist der Unterschied zu einer einfachen Vererbung, dh der Unterschied zu class StickCatcherClass extends Animal { catchStick(){} }? Der Unterschied besteht darin, dass das StickCatcher-Mixin nicht an Animal "gebunden" ist, sondern dass Sie es auch unter vielen anderen Umständen verwenden können, z. B. auch in class StickCatchingDancingRobot extends StickCatcher(Robot) { dance(){} }.
LWCs NavigationMixinsind von ähnlicher Natur. Es fügt die Funktionen für die Navigation und die URL-Generierung Ihrem Klassenprototyp hinzu, fügt sie jedoch unter einigen "hässlichen, nicht widersprüchlichen Funktionsnamen" hinzu. Das NavigationMixin.Navigateist eine statische Zeichenfolge oder Getter bedeutete die sagte „hässlich , aber nicht im Konflikt stehenden Funktionsnamen“ zurückzukehren, so dass this[NavigationMixin.Navigate]Dereferenzierungen an die Navigationsfunktion , die durch die zu Ihrem Prototyp hinzugefügt wurde gesagt , mischen-in.