Heim > Web-Frontend > js-Tutorial > Enthüllung der Magie von JavaScript

Enthüllung der Magie von JavaScript

Lisa Kudrow
Freigeben: 2025-02-21 09:38:10
Original
637 Leute haben es durchsucht

Enthüllung der Magie von JavaScript

Wir verwenden jeden Tag Tonnen von Werkzeugen. Verschiedene Bibliotheken und Frameworks sind Teil unseres täglichen Jobs. Wir verwenden sie, weil wir das Rad für jedes Projekt nicht neu erfinden wollen, auch wenn wir nicht verstehen, was unter der Motorhaube vor sich geht. In diesem Artikel werden wir einige der magischen Prozesse in den beliebtesten Bibliotheken enthüllen. Wir werden auch sehen, ob wir ihr Verhalten replizieren können.

Key Takeaways

  • JavaScript -Bibliotheken wie jQuery vereinfachen DOM -Manipulationen, z. B. das Erstellen von Elementen aus Zeichenfolgen, indem komplexe Fälle wie verschachtelte Elemente korrekt behandelt werden.
  • AngularJS 'Abhängigkeitsinjektionssystem verwaltet die Abhängigkeiten auf magische Weise ohne explizites Verfolgen. Verwenden Sie ein Injektormuster, um zur Laufzeit dynamisch Abhängigkeiten bereitzustellen.
  • ember.js verbessert JavaScript -Objekte mit berechneten Eigenschaften, sodass sich die Eigenschaften wie Funktionen verhalten und automatisch aktualisieren können, wenn sich die Abhängigkeiten ändern.
  • Die JSX -Syntax von
  • React ermöglicht das Einbetten von HTML in JavaScript, das dann durch den JSX -Transformator von React verarbeitet wird, um dynamische UI -Komponenten zu erstellen.
  • Der Artikel zeigt benutzerdefinierte Lösungen für die Abhängigkeitsinjektion und die berechneten Eigenschaften und zeigt, wie Entwickler ähnliche Funktionen in ihren Projekten implementieren können.
  • Verständnis der zugrunde liegenden Mechanik der beliebten JavaScript -Frameworks kann Entwicklern ermöglichen, effizientere und wartbare Code zu schreiben.

DOM -Elemente aus einer String

erstellen

Mit dem Aufstieg einzelner Seitenanwendungen machen wir viele Dinge mit JavaScript. Ein großer Teil der Logik unserer Anwendung wurde in den Browser verschoben. Es ist eine häufige Aufgabe, Elemente auf der Seite zu generieren oder zu ersetzen. Der Code ähnelt dem, was unten gezeigt wird.

<span>var text = $('<div>Simple text</div>');
</span>
<span>$('body').append(text);</span>
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Das Ergebnis ist ein neues

Element, das dem Körper des Dokuments hinzugefügt wurde. Diese einfache Operation erfolgt mit nur einer Zeile JQuery. Ohne JQuery ist der Code etwas komplexer, aber nicht viel:
<span>var stringToDom = function(str) {
</span>  <span>var temp = document.createElement('div');
</span>
  temp<span>.innerHTML = str;
</span>  <span>return temp.childNodes[0];
</span><span>}
</span><span>var text = stringToDom('<div>Simple text</div>');
</span>
<span>document.querySelector('body').appendChild(text);</span>
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Wir haben unsere eigene Versorgungsmethode StringTodom definiert, die ein temporäres

-Element erstellt. Wir haben sein inneres Eigentum geändert und am Ende haben wir einfach das erste Kind zurückgegeben, was in der Praxis das ist, was wir brauchten. Es hat genauso funktioniert. Wir werden jedoch unterschiedliche Ergebnisse mit dem folgenden Code beobachten:
<span>var tableRow = $('<tr><td>Simple text</td></tr>');
</span><span>$('body').append(tableRow);
</span>
<span>var tableRow = stringToDom('<tr><td>Simple text</td></tr>');
</span><span>document.querySelector('body').appendChild(tableRow);</span>
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Visuell gibt es auf der Seite keine Unterschiede. Wenn wir jedoch das generierte Markup mit den Entwicklertools von Chrome überprüfen, erhalten wir ein interessantes Ergebnis:

Enthüllung der Magie von JavaScript

Es sieht so aus, als ob unsere StringTodom -Funktion nur ein Textknoten und nicht das tatsächliche

-Tag erstellt wurde. Gleichzeitig hat JQuery es irgendwie geschafft, es zu tun. Das Problem ist, dass die Zeichenfolge, die das HTML -Element enthält, durch einen Parser im Browser ausgeführt wird. Dieser Parser ignoriert die Tags, die nicht im richtigen Kontext platziert sind, und wir erhalten nur einen Textknoten. Eine Tabellenzeile ohne Tabelle gilt nicht für den Browser.

jQuery löst das Problem erfolgreich, indem er den richtigen Kontext erstellt und nur den erforderlichen Teil extrahiert. Wenn wir ein wenig in den Code der Bibliothek graben, sehen wir eine Karte wie diese:

<span>var text = $('<div>Simple text</div>');
</span>
<span>$('body').append(text);</span>
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Jedes Element, das eine spezielle Behandlung erfordert, hat ein Array zugewiesen. Die Idee ist, das richtige DOM -Element zu konstruieren und sich von der Nestnegerebene abhängig zu machen, um das zu holen, was wir brauchen. Zum Beispiel müssen wir für das

-Element eine Tabelle mit einem -Kind erstellen. Wir haben also zwei Nistniveaus.

Wenn wir eine Karte haben, müssen wir herausfinden, welche Art von Tag wir am Ende wollen. Der folgende Code extrahiert den TR aus

Einfacher Text
<span>var stringToDom = function(str) {
</span>  <span>var temp = document.createElement('div');
</span>
  temp<span>.innerHTML = str;
</span>  <span>return temp.childNodes[0];
</span><span>}
</span><span>var text = stringToDom('<div>Simple text</div>');
</span>
<span>document.querySelector('body').appendChild(text);</span>
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Der Rest findet den richtigen Kontext und die Rückgabe des DOM -Elements. Hier ist die letzte Variante des FunktionsstringTodoms:

<span>var tableRow = $('<tr><td>Simple text</td></tr>');
</span><span>$('body').append(tableRow);
</span>
<span>var tableRow = stringToDom('<tr><td>Simple text</td></tr>');
</span><span>document.querySelector('body').appendChild(tableRow);</span>
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Beachten Sie, dass wir überprüfen, ob es in der Zeichenfolge ein Tag gibt - Übereinstimmung! = NULL. Wenn nicht, geben wir einfach einen Textknoten zurück. Es wird immer noch ein temporäres

verwendet, aber diesmal übergeben wir die richtigen Tags, damit der Browser einen gültigen DOM -Baum erstellen kann. Am Ende nutzen wir eine Weile Schleife immer tiefer, bis wir das gewünschte Tag erreichen.

Hier ist ein CodePen, der unsere Implementierung zeigt:

Siehe den Pen XLCGN von Krasimir TSonev (@Krasimir) auf CodePen.

Lassen Sie uns die wundervolle AngularJS -Abhängigkeitsinjektion untersuchen.

Aufschluss über AngularJS -Abhängigkeitsinjektion

Wenn wir angularJS mithilfe von AngularJs beginnen, beeindruckt es mit seiner Zwei-Wege-Datenbindung. Das zweite, was wir bemerken, ist seine magische Abhängigkeitsinjektion. Hier ist ein einfaches Beispiel:

<span>var wrapMap = {
</span>  <span>option: [1, '<select multiple="multiple">', '</select>'],
</span>  <span>legend: [1, '<fieldset>', '</fieldset>'],
</span>  <span>area: [1, '<map>', '</map>'],
</span>  <span>param: [1, '<object>', '</object>'],
</span>  <span>thead: [1, '<table>', '</table>'],
</span>  <span>tr: [2, '<table><tbody>', '</tbody></table>'],
</span>  <span>col: [2, '<table><tbody></tbody><colgroup>', '</colgroup></table>'],
</span>  <span>td: [3, '<table><tbody><tr>', '</tr></tbody></table>'],
</span>  <span>_default: [1, '<div>', '</div>']
</span><span>};
</span>wrapMap<span>.optgroup = wrapMap.option;
</span>wrapMap<span>.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
</span>wrapMap<span>.th = wrapMap.td;</span>
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Das ist ein typischer AngularJS -Controller. Es führt eine HTTP -Anforderung aus, holt Daten von einer JSON -Datei ab und übergibt sie an den aktuellen Bereich. Wir führen die TodoctRL -Funktion nicht aus - wir haben keine Chance, Argumente zu verabschieden. Das Rahmen tut. Woher kommen diese $ Scope und $ HTTP -Variablen? Es ist eine super coole Funktion, die schwarzen Magie sehr ähnelt. Mal sehen, wie es gemacht wird.

Wir haben eine JavaScript -Funktion, die die Benutzer in unserem System anzeigt. Die gleiche Funktion benötigt Zugriff auf ein DOM -Element, um das generierte HTML und einen AJAX -Wrapper zu setzen, um die Daten zu erhalten. Um das Beispiel zu vereinfachen, werden wir die Daten und die HTTP-Anfrage verspottet.

<span>var text = $('<div>Simple text</div>');
</span>
<span>$('body').append(text);</span>
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Wir werden das

Tag als Inhaltshalter verwenden. AjaxWrapper ist das Objekt, das die Anforderung simuliert, und DataMockup ist ein Array, das unsere Benutzer enthält. Hier ist die Funktion, die wir verwenden werden:
<span>var stringToDom = function(str) {
</span>  <span>var temp = document.createElement('div');
</span>
  temp<span>.innerHTML = str;
</span>  <span>return temp.childNodes[0];
</span><span>}
</span><span>var text = stringToDom('<div>Simple text</div>');
</span>
<span>document.querySelector('body').appendChild(text);</span>
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Und wenn wir DisplayUser (Body, AjaxWrapper) ausführen, werden die drei Namen auf der Seite und /API /in unserer Konsole angeforderten Benutzer angezeigt. Wir könnten sagen, dass unsere Methode zwei Abhängigkeiten hat - Körper und Ajaxwrapper. Jetzt ist es also die Idee, die Funktion funktionieren zu lassen, ohne Argumente zu übergeben, d. H. Wir müssen das gleiche Ergebnis erzielen, indem wir nur DisplayUser () anrufen. Wenn wir dies bisher mit dem Code tun, ist das Ergebnis:

<span>var tableRow = $('<tr><td>Simple text</td></tr>');
</span><span>$('body').append(tableRow);
</span>
<span>var tableRow = stringToDom('<tr><td>Simple text</td></tr>');
</span><span>document.querySelector('body').appendChild(tableRow);</span>
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Und das ist normal, weil der Ajax -Parameter nicht definiert ist.

Die meisten Frameworks, die Mechanismen für die Injektion von Abhängigkeiten bereitstellen, haben ein Modul, das normalerweise Injektor bezeichnet wird. Um eine Abhängigkeit zu verwenden, müssen wir sie dort registrieren. Später, irgendwann, wird unsere Ressource der Logik der Anwendung von demselben Modul zur Verfügung gestellt.

Erstellen wir unseren Injektor:

<span>var wrapMap = {
</span>  <span>option: [1, '<select multiple="multiple">', '</select>'],
</span>  <span>legend: [1, '<fieldset>', '</fieldset>'],
</span>  <span>area: [1, '<map>', '</map>'],
</span>  <span>param: [1, '<object>', '</object>'],
</span>  <span>thead: [1, '<table>', '</table>'],
</span>  <span>tr: [2, '<table><tbody>', '</tbody></table>'],
</span>  <span>col: [2, '<table><tbody></tbody><colgroup>', '</colgroup></table>'],
</span>  <span>td: [3, '<table><tbody><tr>', '</tr></tbody></table>'],
</span>  <span>_default: [1, '<div>', '</div>']
</span><span>};
</span>wrapMap<span>.optgroup = wrapMap.option;
</span>wrapMap<span>.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
</span>wrapMap<span>.th = wrapMap.td;</span>
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Wir brauchen nur zwei Methoden. Der erste, registriert, akzeptiert unsere Ressourcen (Abhängigkeiten) und speichert sie intern. Der zweite akzeptiert das Ziel unserer Injektion - die Funktion, die Abhängigkeiten hat und sie als Parameter erhalten muss. Der Schlüsselmoment hier ist, dass der Injektor unsere Funktion nicht aufrufen sollte. Das ist unsere Aufgabe und wir sollten in der Lage sein, das zu kontrollieren. Was wir in der Auflösungsmethode tun können, ist, einen Schließ zurückzugeben, der das Ziel umrundet und es aufruft. Zum Beispiel:

<span>var match = <span>/&lt;<span>\s*\w.*?&gt;</span>/g</span>.exec(str);
</span><span>var tag = match[0].replace(<span>/&lt;/g</span>, '').replace(<span>/&gt;/g</span>, '');</span>
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Mit diesem Ansatz haben wir die Möglichkeit, die Funktion mit den erforderlichen Abhängigkeiten aufzurufen. Gleichzeitig ändern wir den Workflow der Anwendung nicht. Der Injektor ist immer noch etwas Unabhängiges und hält keine logischen Funktionen.

Die Funktion der DisplayUlers an die Auflösungsmethode hilft natürlich nicht.

<span>var stringToDom = function(str) {
</span>  <span>var wrapMap = {
</span>    <span>option: [1, '<select multiple="multiple">', '</select>'],
</span>    <span>legend: [1, '<fieldset>', '</fieldset>'],
</span>    <span>area: [1, '<map>', '</map>'],
</span>    <span>param: [1, '<object>', '</object>'],
</span>    <span>thead: [1, '<table>', '</table>'],
</span>    <span>tr: [2, '<table><tbody>', '</tbody></table>'],
</span>    <span>col: [2, '<table><tbody></tbody><colgroup>', '</colgroup></table>'],
</span>    <span>td: [3, '<table><tbody><tr>', '</tr></tbody></table>'],
</span>    <span>_default: [1, '<div>', '</div>']
</span>  <span>};
</span>  wrapMap<span>.optgroup = wrapMap.option;
</span>  wrapMap<span>.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
</span>  wrapMap<span>.th = wrapMap.td;
</span>  <span>var element = document.createElement('div');
</span>  <span>var match = <span>/<<span>\s*\w.*?></span>/g</span>.exec(str);
</span>
  <span>if(match != null) {
</span>    <span>var tag = match[0].replace(<span>/</g</span>, '').replace(<span>/>/g</span>, '');
</span>    <span>var map = wrapMap[tag] || wrapMap._default, element;
</span>    str <span>= map[1] + str + map[2];
</span>    element<span>.innerHTML = str;
</span>    <span>// Descend through wrappers to the right content
</span>    <span>var j = map[0]+1;
</span>    <span>while(j--) {
</span>      element <span>= element.lastChild;
</span>    <span>}
</span>  <span>} else {
</span>    <span>// if only text is passed
</span>    element<span>.innerHTML = str;
</span>    element <span>= element.lastChild;
</span>  <span>}
</span>  <span>return element;
</span><span>}</span>
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

wir bekommen immer noch den gleichen Fehler. Der nächste Schritt besteht darin, herauszufinden, was das übergebene Ziel braucht. Was sind seine Abhängigkeiten? Und hier ist der schwierige Teil, den wir von AngularJs übernehmen können. Ich habe wieder ein bisschen in den Code des Framework gegraben und fand Folgendes:

<span>function <span>TodoCtrl</span>($scope<span>, $http</span>) {
</span>  $http<span>.get('users/users.json').success(function(data) {
</span>    $scope<span>.users = data;
</span>  <span>});
</span><span>}</span>
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Wir haben einige Teile absichtlich übersprungen, weil sie eher Implementierungsdetails sind. Das ist der Code, der für uns interessant ist. Die Annotate -Funktion ist so etwas wie unsere Auflösungsmethode. Es konvertiert die übergebene Zielfunktion in eine Zeichenfolge, entfernt die Kommentare (falls vorhanden) und extrahiert die Argumente. Nutzen wir das und sehen die Ergebnisse:

<span>var dataMockup = ['John', 'Steve', 'David'];
</span><span>var body = document.querySelector('body');
</span><span>var ajaxWrapper = {
</span>  <span>get: function(path<span>, cb</span>) {
</span>    <span>console.log(path + ' requested');
</span>    <span>cb(dataMockup);
</span>  <span>}
</span><span>}</span>
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Hier ist die Ausgabe in der Konsole:

Enthüllung der Magie von JavaScript

Wenn wir das zweite Element des Argdecl -Arrays erhalten, werden wir die Namen der erforderlichen Abhängigkeiten finden. Genau das brauchen wir, denn die Namen können die Ressourcen aus der Speicherung des Injektors liefern. Hier ist die Version, die unsere Ziele funktioniert und erfolgreich abdeckt:

<span>var text = $('<div>Simple text</div>');
</span>
<span>$('body').append(text);</span>
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Beachten Sie, dass wir .Split (/,?/G) verwenden, um den String -Domel Ajax in ein Array umzuwandeln. Danach prüfen wir, ob die Abhängigkeiten registriert sind und ob wir sie an die Zielfunktion weitergeben. Der Code außerhalb des Injektors sieht so aus:

<span>var stringToDom = function(str) {
</span>  <span>var temp = document.createElement('div');
</span>
  temp<span>.innerHTML = str;
</span>  <span>return temp.childNodes[0];
</span><span>}
</span><span>var text = stringToDom('<div>Simple text</div>');
</span>
<span>document.querySelector('body').appendChild(text);</span>
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Der Vorteil einer solchen Implementierung besteht darin, dass wir das DOM -Element und den Ajax -Wrapper in vielen Funktionen injizieren können. Wir könnten sogar die Konfiguration unserer Anwendung wie diese verteilen. Es ist nicht erforderlich, Objekte von Unterricht zu Unterricht zu übergeben. Es sind nur die Register- und Auflösungsmethoden.

Natürlich ist unser Injektor nicht perfekt. Es gibt noch einige Raum für Verbesserungen, wie zum Beispiel die Unterstützung der Bereichsumfangsdefinition. Die Zielfunktion ist derzeit mit einem neu erstellten Bereich aufgerufen, aber normalerweise wollen wir unsere eigenen übergeben. Wir sollten auch unterstützen, auch benutzerdefinierte Argumente zusammen mit den Abhängigkeiten zu senden.

Der Injektor wird noch komplizierter, wenn wir unseren Code nach der Minifikation funktionieren möchten. Wie wir wissen, ersetzen die Minifiker die Namen der Funktionen, Variablen und sogar die Argumente der Methoden. Und weil unsere Logik auf diesen Namen beruht, müssen wir über Workaround nachdenken. Eine mögliche Lösung stammt erneut von AngularJs:

<span>var tableRow = $('<tr><td>Simple text</td></tr>');
</span><span>$('body').append(tableRow);
</span>
<span>var tableRow = stringToDom('<tr><td>Simple text</td></tr>');
</span><span>document.querySelector('body').appendChild(tableRow);</span>
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Anstelle der Displayser übergeben wir die Namen der tatsächlichen Abhängigkeiten.

unser Beispiel in Aktion:

Siehe den Stift BXDAR von Krasimir TSonev (@Krasimir) auf CodePen.

die berechneten Eigenschaften von Ember

übernimmt

Ember ist heutzutage eines der beliebtesten Frameworks. Es hat unzählige nützliche Funktionen. Es gibt eine besonders interessante - berechnete Eigenschaften. Zusammenfassend sind berechnete Eigenschaften Funktionen, die als Eigenschaften fungieren. Sehen wir uns ein einfaches Beispiel aus der Dokumentation des Embers:
<span>var wrapMap = {
</span>  <span>option: [1, '<select multiple="multiple">', '</select>'],
</span>  <span>legend: [1, '<fieldset>', '</fieldset>'],
</span>  <span>area: [1, '<map>', '</map>'],
</span>  <span>param: [1, '<object>', '</object>'],
</span>  <span>thead: [1, '<table>', '</table>'],
</span>  <span>tr: [2, '<table><tbody>', '</tbody></table>'],
</span>  <span>col: [2, '<table><tbody></tbody><colgroup>', '</colgroup></table>'],
</span>  <span>td: [3, '<table><tbody><tr>', '</tr></tbody></table>'],
</span>  <span>_default: [1, '<div>', '</div>']
</span><span>};
</span>wrapMap<span>.optgroup = wrapMap.option;
</span>wrapMap<span>.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
</span>wrapMap<span>.th = wrapMap.td;</span>
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Es gibt eine Klasse, die FirstName- und Lastname -Eigenschaften hat. Der Fullname der berechneten Eigenschaft gibt die verkettete Zeichenfolge zurück, die den vollständigen Namen der Person enthält. Das Seltsame ist der Teil, in dem wir eine .Property -Methode gegen die auf Vollnamen angewendete Funktion verwenden. Ich persönlich habe das nirgendwo anders gesehen. Und wiederum enthüllt das schnelle Aussehen des Code des Frameworks die Magie:
<span>var match = <span>/&lt;<span>\s*\w.*?&gt;</span>/g</span>.exec(str);
</span><span>var tag = match[0].replace(<span>/&lt;/g</span>, '').replace(<span>/&gt;/g</span>, '');</span>
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Die Bibliothek optimiert den Prototyp des globalen Funktionsobjekts durch Hinzufügen einer neuen Eigenschaft. Es ist ein schöner Ansatz, während der Definition einer Klasse eine Logik auszuführen.

Ember verwendet Getter und Setter, um mit den Daten des Objekts zu arbeiten. Dies vereinfacht die Implementierung der berechneten Eigenschaften, da wir zuvor eine weitere Ebene haben, um die tatsächlichen Variablen zu erreichen. Es wird jedoch noch interessanter sein, wenn wir berechnete Eigenschaften mit den einfachen JavaScript -Objekten verwenden können. Wie zum Beispiel:

<span>var text = $('<div>Simple text</div>');
</span>
<span>$('body').append(text);</span>
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Name wird als reguläre Eigenschaft verwendet, aber in der Praxis ist eine Funktion, die FirstName und Lastname erhält oder setzt.

Es gibt ein Build-In-Merkmal von JavaScript, das uns helfen könnte, die Idee zu verwirklichen. Schauen Sie sich den folgenden Ausschnitt an:

<span>var stringToDom = function(str) {
</span>  <span>var temp = document.createElement('div');
</span>
  temp<span>.innerHTML = str;
</span>  <span>return temp.childNodes[0];
</span><span>}
</span><span>var text = stringToDom('<div>Simple text</div>');
</span>
<span>document.querySelector('body').appendChild(text);</span>
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Das Object.DefineProperty -Methode könnte einen Umfang, einen Namen einer Eigenschaft, einen Gettter und einen Setter akzeptieren. Wir müssen nur den Körper der beiden Methoden schreiben. Und das war's. Wir werden den obigen Code ausführen und die erwarteten Ergebnisse erhalten:

<span>var tableRow = $('<tr><td>Simple text</td></tr>');
</span><span>$('body').append(tableRow);
</span>
<span>var tableRow = stringToDom('<tr><td>Simple text</td></tr>');
</span><span>document.querySelector('body').appendChild(tableRow);</span>
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Object.DefineProperty ist genau das, was wir brauchen, aber wir möchten den Entwickler nicht zwingen, ihn jedes Mal zu schreiben. Möglicherweise müssen wir eine Polyfüllung bereitstellen, zusätzliche Logik oder ähnliches ausführen. Im idealen Fall möchten wir eine Schnittstelle ähnlich wie die von Ember bereitstellen. Nur eine Funktion ist Teil der Klassendefinition. In diesem Abschnitt schreiben wir eine Dienstprogrammfunktion namens Computize, die unser Objekt verarbeitet und irgendwie die Namensfunktion mit demselben Namen in eine Eigenschaft umwandelt.

<span>var wrapMap = {
</span>  <span>option: [1, '<select multiple="multiple">', '</select>'],
</span>  <span>legend: [1, '<fieldset>', '</fieldset>'],
</span>  <span>area: [1, '<map>', '</map>'],
</span>  <span>param: [1, '<object>', '</object>'],
</span>  <span>thead: [1, '<table>', '</table>'],
</span>  <span>tr: [2, '<table><tbody>', '</tbody></table>'],
</span>  <span>col: [2, '<table><tbody></tbody><colgroup>', '</colgroup></table>'],
</span>  <span>td: [3, '<table><tbody><tr>', '</tr></tbody></table>'],
</span>  <span>_default: [1, '<div>', '</div>']
</span><span>};
</span>wrapMap<span>.optgroup = wrapMap.option;
</span>wrapMap<span>.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
</span>wrapMap<span>.th = wrapMap.td;</span>
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

wir möchten die Namensmethode als Setter und gleichzeitig wie ein Getter verwenden. Dies ähnelt den berechneten Eigenschaften von Ember.

Lassen Sie uns jetzt unsere eigene Logik in den Prototyp des Funktionsobjekts hinzufügen:

<span>var match = <span>/&lt;<span>\s*\w.*?&gt;</span>/g</span>.exec(str);
</span><span>var tag = match[0].replace(<span>/&lt;/g</span>, '').replace(<span>/&gt;/g</span>, '');</span>
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Sobald wir die obigen Zeilen hinzufügen, können wir. Computed () zum Ende jeder Funktionsdefinition hinzufügen:

<span>var stringToDom = function(str) {
</span>  <span>var wrapMap = {
</span>    <span>option: [1, '<select multiple="multiple">', '</select>'],
</span>    <span>legend: [1, '<fieldset>', '</fieldset>'],
</span>    <span>area: [1, '<map>', '</map>'],
</span>    <span>param: [1, '<object>', '</object>'],
</span>    <span>thead: [1, '<table>', '</table>'],
</span>    <span>tr: [2, '<table><tbody>', '</tbody></table>'],
</span>    <span>col: [2, '<table><tbody></tbody><colgroup>', '</colgroup></table>'],
</span>    <span>td: [3, '<table><tbody><tr>', '</tr></tbody></table>'],
</span>    <span>_default: [1, '<div>', '</div>']
</span>  <span>};
</span>  wrapMap<span>.optgroup = wrapMap.option;
</span>  wrapMap<span>.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
</span>  wrapMap<span>.th = wrapMap.td;
</span>  <span>var element = document.createElement('div');
</span>  <span>var match = <span>/<<span>\s*\w.*?></span>/g</span>.exec(str);
</span>
  <span>if(match != null) {
</span>    <span>var tag = match[0].replace(<span>/</g</span>, '').replace(<span>/>/g</span>, '');
</span>    <span>var map = wrapMap[tag] || wrapMap._default, element;
</span>    str <span>= map[1] + str + map[2];
</span>    element<span>.innerHTML = str;
</span>    <span>// Descend through wrappers to the right content
</span>    <span>var j = map[0]+1;
</span>    <span>while(j--) {
</span>      element <span>= element.lastChild;
</span>    <span>}
</span>  <span>} else {
</span>    <span>// if only text is passed
</span>    element<span>.innerHTML = str;
</span>    element <span>= element.lastChild;
</span>  <span>}
</span>  <span>return element;
</span><span>}</span>
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Infolgedessen enthält die Namenseigenschaft keine Funktion mehr, sondern ein Objekt, das die Eigenschaft der tatsächlichen und func -Eigenschaft berechnet hat, die mit der alten Funktion gefüllt ist. Die wirkliche Magie geschieht bei der Implementierung des Computize -Helfers. Es durchläuft alle Eigenschaften des Objekts und verwendet Object.defineProperty, wo wir Eigenschaften berechnet haben:

<span>function <span>TodoCtrl</span>($scope<span>, $http</span>) {
</span>  $http<span>.get('users/users.json').success(function(data) {
</span>    $scope<span>.users = data;
</span>  <span>});
</span><span>}</span>
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Beachten Sie, dass wir den ursprünglichen Eigenschaftsnamen löschen. In einigen Browser -Objekten. DefineProperty arbeitet nur für Eigenschaften, die noch nicht definiert sind.

Hier ist die endgültige Version des Benutzerobjekts, das die. Computed () -Funktion verwendet.

<span>var dataMockup = ['John', 'Steve', 'David'];
</span><span>var body = document.querySelector('body');
</span><span>var ajaxWrapper = {
</span>  <span>get: function(path<span>, cb</span>) {
</span>    <span>console.log(path + ' requested');
</span>    <span>cb(dataMockup);
</span>  <span>}
</span><span>}</span>
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Eine Funktion, die den vollständigen Namen zurückgibt, wird zum Ändern von FirstName und LastName verwendet. Das ist die Idee hinter der Überprüfung bestandener Argumente und der Verarbeitung des ersten. Wenn es existiert, teilen wir es auf und wenden die Werte auf die normalen Eigenschaften an.

Wir haben bereits die gewünschte Verwendung erwähnt, aber lassen Sie es uns noch einmal sehen:

<span>var displayUsers = function(domEl<span>, ajax</span>) {
</span>  ajax<span>.get('/api/users', function(users) {
</span>    <span>var html = '';
</span>    <span>for(var i=0; i < users.length; i++) {
</span>      html <span>+= '<p>' + users[i] + '</p>';
</span>    <span>}
</span>    domEl<span>.innerHTML = html;
</span>  <span>});
</span><span>}</span>
Nach dem Login kopieren

Die folgende CodePen zeigt unsere Arbeit in der Praxis:

Siehe den Pen Ahpqo von Krasimir TSonev (@Krasimir) auf CodePen.

Die verrückten React -Vorlagen

Sie haben wahrscheinlich von Facebooks Framework React gehört. Es basiert auf der Idee, dass alles eine Komponente ist. Interessant ist die Definition der Komponente. Schauen wir uns das folgende Beispiel an:

<span>var text = $('<div>Simple text</div>');
</span>
<span>$('body').append(text);</span>
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Das erste, worüber wir nachdenken, ist, dass dies ein JavaScript ist, aber es ist ein ungültiges. Es gibt eine Renderfunktion und wird wahrscheinlich einen Fehler werfen. Der Trick ist jedoch, dass dieser Code mit einem benutzerdefinierten Typ -Attribut in <script> -TAG eingegeben wird. Der Browser verarbeitet es nicht, was bedeutet, dass wir vor Fehlern sicher sind. React hat einen eigenen Parser, der den von uns geschriebenen Code in ein gültiges JavaScript übersetzt. Die Entwickler von Facebook bezeichneten die XML -ähnliche Sprache <em> jsx . Ihr JSX -Transformator ist 390.000 und enthält ungefähr 12000 Codezeilen. Es ist also etwas komplex. In diesem Abschnitt werden wir etwas Einfaches, aber immer noch ziemlich mächtig schaffen. Eine JavaScript -Klasse, die HTML -Vorlagen im Reaktionsstil analysiert. </script>

Der Ansatz, den Facebook verfolgte, besteht darin, den JavaScript -Code mit HTML Markup zu mischen. Nehmen wir also an, wir haben die folgende Vorlage:

<span>var stringToDom = function(str) {
</span>  <span>var temp = document.createElement('div');
</span>
  temp<span>.innerHTML = str;
</span>  <span>return temp.childNodes[0];
</span><span>}
</span><span>var text = stringToDom('<div>Simple text</div>');
</span>
<span>document.querySelector('body').appendChild(text);</span>
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

und eine Komponente, die es verwendet:

<span>var tableRow = $('<tr><td>Simple text</td></tr>');
</span><span>$('body').append(tableRow);
</span>
<span>var tableRow = stringToDom('<tr><td>Simple text</td></tr>');
</span><span>document.querySelector('body').appendChild(tableRow);</span>
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Die Idee ist, dass wir auf die ID der Vorlage hinweisen und die angewendeten Daten definieren. Der letzte Teil unserer Implementierung ist die tatsächliche Engine, die die beiden Elemente verschmilzt. Nennen wir es Engine und starten Sie es so:

<span>var wrapMap = {
</span>  <span>option: [1, '<select multiple="multiple">', '</select>'],
</span>  <span>legend: [1, '<fieldset>', '</fieldset>'],
</span>  <span>area: [1, '<map>', '</map>'],
</span>  <span>param: [1, '<object>', '</object>'],
</span>  <span>thead: [1, '<table>', '</table>'],
</span>  <span>tr: [2, '<table><tbody>', '</tbody></table>'],
</span>  <span>col: [2, '<table><tbody></tbody><colgroup>', '</colgroup></table>'],
</span>  <span>td: [3, '<table><tbody><tr>', '</tr></tbody></table>'],
</span>  <span>_default: [1, '<div>', '</div>']
</span><span>};
</span>wrapMap<span>.optgroup = wrapMap.option;
</span>wrapMap<span>.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
</span>wrapMap<span>.th = wrapMap.td;</span>
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Wir erhalten den Inhalt des tag. Analysieren und HTML -Zeichenfolge erzeugen. Konvertieren Sie diese HTML in ein gültiges DOM -Element und geben Sie es als Ergebnis des gesamten Prozesses zurück. Beachten Sie, dass wir die StringTodom -Funktion verwenden. Der, den wir im ersten Abschnitt dieses Artikels geschrieben haben.

Schreiben wir jetzt unsere Parse -Funktion. Unsere erste Aufgabe ist es, die HTML von den Ausdrücken zu unterscheiden. Mit Ausdrücken meinen wir Strings zwischen . Wir werden einen Regex verwenden, um sie und eine einfache während der Schleife zu finden, um alle Übereinstimmungen durchzugehen:

<span>var match = <span>/&lt;<span>\s*\w.*?&gt;</span>/g</span>.exec(str);
</span><span>var tag = match[0].replace(<span>/&lt;/g</span>, '').replace(<span>/&gt;/g</span>, '');</span>
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Das Ergebnis des obigen Codes lautet wie folgt:

<span>var stringToDom = function(str) {
</span>  <span>var wrapMap = {
</span>    <span>option: [1, '<select multiple="multiple">', '</select>'],
</span>    <span>legend: [1, '<fieldset>', '</fieldset>'],
</span>    <span>area: [1, '<map>', '</map>'],
</span>    <span>param: [1, '<object>', '</object>'],
</span>    <span>thead: [1, '<table>', '</table>'],
</span>    <span>tr: [2, '<table><tbody>', '</tbody></table>'],
</span>    <span>col: [2, '<table><tbody></tbody><colgroup>', '</colgroup></table>'],
</span>    <span>td: [3, '<table><tbody><tr>', '</tr></tbody></table>'],
</span>    <span>_default: [1, '<div>', '</div>']
</span>  <span>};
</span>  wrapMap<span>.optgroup = wrapMap.option;
</span>  wrapMap<span>.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
</span>  wrapMap<span>.th = wrapMap.td;
</span>  <span>var element = document.createElement('div');
</span>  <span>var match = <span>/<<span>\s*\w.*?></span>/g</span>.exec(str);
</span>
  <span>if(match != null) {
</span>    <span>var tag = match[0].replace(<span>/</g</span>, '').replace(<span>/>/g</span>, '');
</span>    <span>var map = wrapMap[tag] || wrapMap._default, element;
</span>    str <span>= map[1] + str + map[2];
</span>    element<span>.innerHTML = str;
</span>    <span>// Descend through wrappers to the right content
</span>    <span>var j = map[0]+1;
</span>    <span>while(j--) {
</span>      element <span>= element.lastChild;
</span>    <span>}
</span>  <span>} else {
</span>    <span>// if only text is passed
</span>    element<span>.innerHTML = str;
</span>    element <span>= element.lastChild;
</span>  <span>}
</span>  <span>return element;
</span><span>}</span>
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Es gibt nur einen Ausdruck und sein Inhalt ist der Titel. Der erste intuitive Ansatz, den wir verfolgen können, ist die Verwendung der Ersatzfunktion des JavaScripts und Ersatz für den Title %> durch die Daten aus dem bestandenen Comp -Objekt. Dies funktioniert jedoch nur mit den einfachen Eigenschaften. Was ist, wenn wir verschachtelte Objekte haben oder auch wenn wir eine Funktion verwenden möchten? Wie zum Beispiel:

<span>function <span>TodoCtrl</span>($scope<span>, $http</span>) {
</span>  $http<span>.get('users/users.json').success(function(data) {
</span>    $scope<span>.users = data;
</span>  <span>});
</span><span>}</span>
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Anstatt einen komplexen Parser zu erstellen und eine neue Sprache fast zu erfinden, verwenden wir möglicherweise reines JavaScript. Das einzige, was wir tun müssen, ist die neue Funktionssyntax zu verwenden.

<span>var dataMockup = ['John', 'Steve', 'David'];
</span><span>var body = document.querySelector('body');
</span><span>var ajaxWrapper = {
</span>  <span>get: function(path<span>, cb</span>) {
</span>    <span>console.log(path + ' requested');
</span>    <span>cb(dataMockup);
</span>  <span>}
</span><span>}</span>
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Wir sind in der Lage, den Körper einer Funktion zu konstruieren, die später ausgeführt wird. Wir kennen also die Position unserer Ausdrücke und was genau dahinter steht. Wenn wir ein temporäres Array und einen Cursor verwenden, sieht unser While -Zyklus so aus:

<span>var text = $('<div>Simple text</div>');
</span>
<span>$('body').append(text);</span>
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Die Ausgabe in der Konsole zeigt, dass wir uns auf dem richtigen Weg befinden:

<span>var stringToDom = function(str) {
</span>  <span>var temp = document.createElement('div');
</span>
  temp<span>.innerHTML = str;
</span>  <span>return temp.childNodes[0];
</span><span>}
</span><span>var text = stringToDom('<div>Simple text</div>');
</span>
<span>document.querySelector('body').appendChild(text);</span>
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Das Code -Array sollte in eine Zeichenfolge umgewandelt werden, die eine Funktion eines Funktion ist. Zum Beispiel:

<span>var tableRow = $('<tr><td>Simple text</td></tr>');
</span><span>$('body').append(tableRow);
</span>
<span>var tableRow = stringToDom('<tr><td>Simple text</td></tr>');
</span><span>document.querySelector('body').appendChild(tableRow);</span>
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Es ist ziemlich einfach, dieses Ergebnis zu erzielen. Wir können eine Schleife schreiben, die alle Elemente des Code -Arrays durchläuft und überprüft, ob es sich bei dem Element um eine Zeichenfolge oder ein Objekt handelt. Dies deckt jedoch erneut nur einen Teil der Fälle ab. Was ist, wenn wir die folgende Vorlage haben:

<span>var wrapMap = {
</span>  <span>option: [1, '<select multiple="multiple">', '</select>'],
</span>  <span>legend: [1, '<fieldset>', '</fieldset>'],
</span>  <span>area: [1, '<map>', '</map>'],
</span>  <span>param: [1, '<object>', '</object>'],
</span>  <span>thead: [1, '<table>', '</table>'],
</span>  <span>tr: [2, '<table><tbody>', '</tbody></table>'],
</span>  <span>col: [2, '<table><tbody></tbody><colgroup>', '</colgroup></table>'],
</span>  <span>td: [3, '<table><tbody><tr>', '</tr></tbody></table>'],
</span>  <span>_default: [1, '<div>', '</div>']
</span><span>};
</span>wrapMap<span>.optgroup = wrapMap.option;
</span>wrapMap<span>.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
</span>wrapMap<span>.th = wrapMap.td;</span>
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Wir können nicht nur die Ausdrücke verkettet und erwarten, dass die Farben aufgelistet sind. Anstatt eine Zeichenfolge an eine String anzuhängen, werden wir sie in einem Array sammeln. Hier ist die aktualisierte Version der Parse -Funktion:

<span>var match = <span>/&lt;<span>\s*\w.*?&gt;</span>/g</span>.exec(str);
</span><span>var tag = match[0].replace(<span>/&lt;/g</span>, '').replace(<span>/&gt;/g</span>, '');</span>
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Sobald das Code -Array gefüllt ist, beginnen wir mit der Erstellung des Körpers der Funktion. Jede Zeile der Vorlage wird in einem Array r gespeichert. Wenn es sich bei der Zeile um eine Zeichenfolge handelt, klären wir sie ein wenig, indem wir den Zitaten entkommen und die neuen Zeilen und Registerkarten entfernen. Das Array wird über die Push -Methode hinzugefügt. Wenn wir ein Code -Snippet haben, überprüfen wir, ob es sich nicht um einen gültigen JavaScript -Operator handelt. Wenn ja, dann fügen wir es dem Array nicht hinzu, sondern löschen es einfach als neue Zeile. Die Konsole.log am Ende Ausgänge:

<span>var stringToDom = function(str) {
</span>  <span>var wrapMap = {
</span>    <span>option: [1, '<select multiple="multiple">', '</select>'],
</span>    <span>legend: [1, '<fieldset>', '</fieldset>'],
</span>    <span>area: [1, '<map>', '</map>'],
</span>    <span>param: [1, '<object>', '</object>'],
</span>    <span>thead: [1, '<table>', '</table>'],
</span>    <span>tr: [2, '<table><tbody>', '</tbody></table>'],
</span>    <span>col: [2, '<table><tbody></tbody><colgroup>', '</colgroup></table>'],
</span>    <span>td: [3, '<table><tbody><tr>', '</tr></tbody></table>'],
</span>    <span>_default: [1, '<div>', '</div>']
</span>  <span>};
</span>  wrapMap<span>.optgroup = wrapMap.option;
</span>  wrapMap<span>.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
</span>  wrapMap<span>.th = wrapMap.td;
</span>  <span>var element = document.createElement('div');
</span>  <span>var match = <span>/<<span>\s*\w.*?></span>/g</span>.exec(str);
</span>
  <span>if(match != null) {
</span>    <span>var tag = match[0].replace(<span>/</g</span>, '').replace(<span>/>/g</span>, '');
</span>    <span>var map = wrapMap[tag] || wrapMap._default, element;
</span>    str <span>= map[1] + str + map[2];
</span>    element<span>.innerHTML = str;
</span>    <span>// Descend through wrappers to the right content
</span>    <span>var j = map[0]+1;
</span>    <span>while(j--) {
</span>      element <span>= element.lastChild;
</span>    <span>}
</span>  <span>} else {
</span>    <span>// if only text is passed
</span>    element<span>.innerHTML = str;
</span>    element <span>= element.lastChild;
</span>  <span>}
</span>  <span>return element;
</span><span>}</span>
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Schön, nicht wahr? Ordnungsgemäß formatiertes funktionierendes JavaScript, das im Kontext unserer Komponente ausgeführt wird, erzeugt das gewünschte HTML -Markup.

Das Letzte, was übrig bleibt, ist das tatsächliche Ausführen unserer praktisch erstellten Funktion:

<span>function <span>TodoCtrl</span>($scope<span>, $http</span>) {
</span>  $http<span>.get('users/users.json').success(function(data) {
</span>    $scope<span>.users = data;
</span>  <span>});
</span><span>}</span>
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Wir haben unseren Code in eine mit Anweisung eingewickelt, um ihn im Kontext der Komponente auszuführen. Ohne das müssen wir diesen und diese. Colors anstelle von Titel und Farben verwenden.

Hier zeigt ein Codepen das Endergebnis:

Siehe den Pen Gahej von Krasimir TSonev (@Krasimir) auf CodePen.

Zusammenfassung

Hinter den großen Frameworks und Bibliotheken befinden sich intelligente Entwickler. Sie fanden und verwenden knifflige Lösungen, die nicht trivial und sogar irgendwie magisch sind. In diesem Artikel haben wir einige dieser Magie enthüllt. Es ist schön, dass wir in der JavaScript -Welt aus dem Besten lernen und ihren Code verwenden können.

Der Code aus diesem Artikel kann von Github

heruntergeladen werden

häufig gestellte Fragen (FAQs) zur Magie von JavaScript

Was sind magische Methoden in JavaScript und wie funktionieren sie? Sie werden nicht direkt aufgerufen, sondern aufgerufen, wenn bestimmte Aktionen ausgeführt werden. Beispielsweise ist die Methode toString () eine magische Methode, die automatisch aufgerufen wird, wenn ein Objekt als Textwert dargestellt werden muss. Ein weiteres Beispiel ist die ValueOf () -Methode, die aufgerufen wird, wenn ein Objekt als primitiven Wert dargestellt werden soll.

Wie kann ich magische Methoden in JavaScript verwenden? Sie können beispielsweise eine ToString () -Methode in Ihrem Objekt definieren, um anzupassen, wie Ihr Objekt als Zeichenfolge dargestellt wird. Hier ist ein einfaches Beispiel:

let person = {
FirstName: "John",
LastName: "doe",
toString: function () {
return this.firstname "zurück" "this.lastName;
}
}; // "John Doe"

Welche Bedeutung haben magische Funktionen in JavaScript? Sie können Ihren Code intuitiver und einfacher zu verstehen und Ihre Daten zu verkapulieren und zu schützen. Hier sind einige Beispiele für magische Funktionen in JavaScript:

1. toString (): Diese Methode gibt eine Zeichenfolge zurück, die das Objekt darstellt.

1. valueOf (): Diese Methode gibt den primitiven Wert des Objekts zurück.


1. HasownProperty (): Diese Methode gibt einen Booleschen zurück, der angibt, ob das Objekt die angegebene Eigenschaft hat. Magische Methoden können sehr nützlich sein, sie haben auch einige Einschränkungen. Zum einen können sie Ihren Code komplexer und debuggerer machen, insbesondere wenn Sie nicht mit der Funktionsweise vertraut sind. Sie können auch zu unerwartetem Verhalten führen, wenn sie nicht korrekt verwendet werden. "Magische Methoden". Es gibt jedoch bestimmte Methoden, die sich ähnlich verhalten, wie z. B. toString () und valueof (). Diese Methoden werden in bestimmten Situationen automatisch aufgerufen, ähnlich wie magische Methoden in anderen Sprachen. Geben Sie das Verständnis ein, wann und warum Sie sie verwenden, um sie sparsam zu verwenden, um Komplexität zu vermeiden, und testen Sie Ihren Code immer gründlich, um sicherzustellen, dass er sich wie erwartet verhält. Frameworks wie React oder Vue? Die Art und Weise, wie sie verwendet werden, kann jedoch je nach Rahmen variieren. Es ist immer am besten, sich auf die Dokumentation des spezifischen Frameworks zu beziehen.

Wie kann ich mehr über magische Methoden in JavaScript erfahren? Sie können mit der offiziellen JavaScript -Dokumentation sowie mit Online -Tutorials und -kursen beginnen. Sie können sie auch in Ihren eigenen Projekten üben, um praktische Erfahrungen zu sammeln. Tools, die bei der Verwendung magischer Methoden in JavaScript helfen können. Zum Beispiel ist Lodash eine beliebte JavaScript -Dienstprogrammbibliothek, die hilfreiche Methoden für die Arbeit mit Arrays, Objekten und anderen Datenarten bietet.

Das obige ist der detaillierte Inhalt vonEnthüllung der Magie von JavaScript. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Neueste Artikel des Autors
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage