tl; dr: Ist es möglich, eine wiederverwendbare Vorlage wörtlich zu machen?
Ich habe versucht, Vorlagenliterale zu verwenden, aber ich glaube, ich verstehe es einfach nicht und jetzt bin ich frustriert. Ich meine, ich denke ich verstehe es, aber "es" sollte nicht so sein, wie es funktioniert oder wie es werden sollte. Es sollte anders werden.
Alle Beispiele, die ich sehe (sogar mit Tags versehene Vorlagen), erfordern, dass die "Ersetzungen" zur Deklarationszeit und nicht zur Laufzeit erfolgen, was mir für eine Vorlage völlig nutzlos erscheint. Vielleicht bin ich verrückt, aber eine "Vorlage" ist für mich ein Dokument, das Token enthält, die ersetzt werden, wenn Sie es verwenden, nicht wenn Sie es erstellen, sonst ist es nur ein Dokument (dh eine Zeichenfolge). Eine Vorlage wird mit den Token als Token gespeichert und diese Token werden ausgewertet, wenn Sie ... sie auswerten.
Jeder zitiert ein schreckliches Beispiel ähnlich:
var a = 'asd';
return `Worthless ${a}!`
Das ist schön, aber wenn ich es schon weiß a
, würde ich einfach return 'Worthless asd'
oder return 'Worthless '+a
. Was ist der Punkt? Ernsthaft. Okay, der Punkt ist Faulheit; weniger Pluspunkte, mehr Lesbarkeit. Toll. Aber das ist keine Vorlage! Nicht IMHO. Und MHO ist alles was zählt! Das Problem, IMHO, ist, dass die Vorlage ausgewertet wird, wenn sie deklariert wird. Wenn Sie dies tun, IMHO:
var tpl = `My ${expletive} template`;
function go() { return tpl; }
go(); // SPACE-TIME ENDS!
Da expletive
nicht deklariert ist, gibt es so etwas wie aus My undefined template
. Super. Zumindest in Chrome kann ich die Vorlage nicht einmal deklarieren. es wird ein Fehler ausgegeben, weil expletive
nicht definiert ist. Was ich brauche, ist in der Lage zu sein, die Ersetzung nach dem Deklarieren der Vorlage durchzuführen:
var tpl = `My ${expletive} template`;
function go() { return tpl; }
var expletive = 'great';
go(); // My great template
Ich sehe jedoch nicht, wie dies möglich ist, da dies keine wirklichen Vorlagen sind. Selbst wenn Sie sagen, ich sollte Tags verwenden, nein, sie funktionieren nicht:
> explete = function(a,b) { console.log(a); console.log(b); }
< function (a,b) { console.log(a); console.log(b); }
> var tpl = explete`My ${expletive} template`
< VM2323:2 Uncaught ReferenceError: expletive is not defined...
Dies alles hat mich zu der Überzeugung geführt, dass Vorlagenliterale schrecklich falsch benannt sind und so genannt werden sollten, wie sie wirklich sind: Heredocs . Ich denke, der "wörtliche" Teil hätte mich darauf hinweisen sollen (wie in, unveränderlich)?
Vermisse ich etwas Gibt es eine (gute) Möglichkeit, eine wiederverwendbare Vorlage wörtlich zu machen?
Ich gebe Ihnen wiederverwendbare Vorlagenliterale :
> function out(t) { console.log(eval(t)); }
var template = `\`This is
my \${expletive} reusable
template!\``;
out(template);
var expletive = 'curious';
out(template);
var expletive = 'AMAZING';
out(template);
< This is
my undefined reusable
template!
This is
my curious reusable
template!
This is
my AMAZING reusable
template!
Und hier ist eine naive "Helfer" -Funktion ...
function t(t) { return '`'+t.replace('{','${')+'`'; }
var template = t(`This is
my {expletive} reusable
template!`);
...um es besser zu machen".
Ich neige dazu, sie Template-Gutenals zu nennen, weil sie in diesem Bereich verdrehte Gefühle hervorrufen.
<strike>
Tag ein.Antworten:
Damit diese Literale wie andere Template-Engines funktionieren, muss es eine Zwischenform geben.
Der beste Weg, dies zu tun, ist die Verwendung des
Function
Konstruktors.Wie bei anderen Template-Engines können Sie diese Zeichenfolge von anderen Stellen wie einer Datei abrufen.
Bei dieser Methode kann es Probleme geben, z. B. sind Vorlagen-Tags schwer zu verwenden. Diese können jedoch hinzugefügt werden, wenn Sie klug sind. Aufgrund der späten Interpolation können Sie auch keine Inline-JavaScript-Logik verwenden. Dies kann auch mit einigem Nachdenken behoben werden.
quelle
new Function(`return \`${template}\`;`)
Sie können eine Vorlagenzeichenfolge in eine Funktion einfügen:
Mit einer getaggten Vorlage können Sie dasselbe tun:
Die Idee ist, den Vorlagenparser die konstanten Zeichenfolgen von den variablen "Slots" trennen zu lassen und dann eine Funktion zurückzugeben, die alles basierend auf einem neuen Wertesatz jedes Mal wieder zusammenfügt.
quelle
reusable
könnte so implementiert werden, dass es eine Funktion zurückgibt, und Sie würden${0}
und${1}
innerhalb des Literals anstelle von${a}
und verwenden${b}
. Dann können Sie diese Werte verwenden, um auf die Argumente der Funktion zu verweisen, ähnlich wie Bergi es in seinem letzten Beispiel getan hat : stackoverflow.com/a/22619256/218196 (oder ich denke, es ist im Grunde dasselbe).expression`a + ${node}`
ein BinaryExpression-Knoten mit einem vorhandenen AST-Knoten erstellt werdennode
. Intern fügen wir einen Platzhalter ein, um gültigen Code zu generieren, analysieren ihn als AST und ersetzen den Platzhalter durch den übergebenen Wert.Der wahrscheinlich sauberste Weg, dies zu tun, sind Pfeilfunktionen (da wir zu diesem Zeitpunkt bereits ES6 verwenden).
... und für getaggte Vorlagenliterale:
Dies vermeidet auch die Verwendung von
eval()
oderFunction()
was Probleme mit Compilern verursachen und viel Verlangsamung verursachen kann.quelle
myTag
zu tun. Verwenden Sie beispielsweise die Eingabeparameter als Schlüssel zum Zwischenspeichern der Ausgabe.var reusable = (value: string) => `Value is ${value}`
.Antwort 2019 :
Hinweis : Die Bibliothek erwartete ursprünglich, dass Benutzer Zeichenfolgen bereinigen, um XSS zu vermeiden. In Version 2 der Bibliothek müssen Benutzerzeichenfolgen nicht mehr bereinigt werden (was Webentwickler sowieso tun sollten), da dies
eval
vollständig vermieden wird .Das
es6-dynamic-template
Modul auf npm macht das.Im Gegensatz zu den aktuellen Antworten:
this
in der VorlagenzeichenfolgeDie Verwendung ist einfach. Verwenden Sie einfache Anführungszeichen, da die Vorlagenzeichenfolge später aufgelöst wird!
quelle
10 * 20 = ${10 * 20}
, es könnte ein ähnliches Format sein, aber es ist nicht einmal aus der Ferne es6 Template-LiteraleJa, Sie können dies tun, indem Sie Ihre Zeichenfolge mit der Vorlage als JS von
Function
(odereval
) analysieren. Dies wird jedoch nicht empfohlen und ermöglicht einen XSS-AngriffCode-Snippet anzeigen
Stattdessen können Sie Objektfelder wie folgt sicher auf dynamische Weise
obj
in die Vorlage einfügenstr
Code-Snippet anzeigen
quelle
.*?
bedeutet nicht gierig - wenn Sie entfernen,"?"
dann Snippet wird falsches Ergebnis gebenfunction taggedTemplate(template, data, matcher) { if (!template || !data) { return template; } matcher = matcher || /{(\w*)}/g; // {one or more alphanumeric characters with no spaces} return template.replace(matcher, function (match, key) { var value; try { value = data[key] } catch (e) { // } return value || ""; }); }
data = { a: 1, b: { c:2, d:3 } }
->b.c
?Vereinfachung der Antwort von @metamorphasi;
quelle
eval
.var hosting
) .Wenn Sie möchten , um die Variablen in der Vorlage referenzieren nicht verwenden geordneten Parameter oder Kontext / Namensräume, zum Beispiel
${0}
,${this.something}
oder${data.something}
können Sie eine Template - Funktion haben , die Pflege des Scoping für Sie nimmt.Beispiel, wie Sie eine solche Vorlage aufrufen können:
Die Vorlagenfunktion:
Die Besonderheit in diesem Fall ist, dass Sie nur eine Funktion übergeben müssen (im Beispiel habe ich eine Pfeilfunktion verwendet), die das ES6-Vorlagenliteral zurückgibt. Ich denke, es ist ein kleiner Kompromiss, die Art von wiederverwendbarer Interpolation zu erhalten, nach der wir suchen.
Hier ist es auf GitHub: https://github.com/Adelphos/ES6-Reuseable-Template
quelle
Object.values()
undObject.keys()
Die kurze Antwort lautet: Verwenden Sie einfach _.template in lodash
quelle
Vielleicht bin ich etwas fehlt, weil meine Lösung für dieses Problem zu mir so offensichtlich scheint , dass ich sehr überrascht , niemand bin, der schrieb bereits in einem so alten Frage.
Ich habe einen fast einzeiligen dafür:
Das ist alles. Wenn ich eine Vorlage wiederverwenden und die Auflösung der Ersetzungen verschieben möchte, mache ich einfach:
Durch Anwenden dieses Tags wird ein
'function'
(anstelle von a'string'
) zurückgegeben, das alle an das Literal übergebenen Parameter ignoriert. Dann kann es später mit neuen Parametern aufgerufen werden. Wenn ein Parameter kein entsprechendes Ersetzen hat, wird es'undefined'
.Erweiterte Antwort
Dieser einfache Code ist funktionsfähig, aber wenn Sie ein ausgefeilteres Verhalten benötigen, kann dieselbe Logik angewendet werden und es gibt endlose Möglichkeiten. Du könntest:
Sie können die an das Literal übergebenen Originalwerte in der Konstruktion speichern und beim Anwenden der Vorlage auf kreative Weise verwenden. Sie können zu Flags, Typvalidatoren, Funktionen usw. werden. In diesem Beispiel werden sie als Standardwerte verwendet:
Dann:
Schließen Sie dazu diese Logik in eine Funktion ein, die als Argument eine benutzerdefinierte Funktion erwartet, die in der Reduktion angewendet werden kann (beim Verbinden der Teile des Vorlagenliteral) und eine neue Vorlage mit benutzerdefiniertem Verhalten zurückgibt.
Dann könnten Sie beispielsweise Vorlagen schreiben, die beim Schreiben von eingebettetem HTML, CSS, SQL, Bash ... automatisch entkommen oder Parameter bereinigen.
Mit dieser naiven (ich wiederhole, naiven! ) SQL-Vorlage könnten wir Abfragen wie diese erstellen:
Akzeptieren Sie benannte Parameter für die Substitution: Eine nicht so schwierige Übung, basierend auf dem, was bereits gegeben wurde. Diese andere Antwort enthält eine Implementierung .
Stellen Sie sicher, dass sich das Rückgabeobjekt wie
'string'
folgt verhält : Nun, das ist umstritten, könnte aber zu interessanten Ergebnissen führen. In dieser anderen Antwort gezeigt .Lösen Sie Parameter im globalen Namespace am Aufrufstandort auf:
Nun, das ist, was OP gezeigt hat, ist sein Nachtrag, mit dem Befehl
, ich meine ,evil
eval
. Dies kann ohne daseval
Durchsuchen des übergebenen Variablennamens in das globale (oder Fenster-) Objekt erfolgen. Ich werde nicht zeigen, wie es geht, weil es mir nicht gefällt. Verschlüsse sind die richtige Wahl.quelle
Dies ist mein bester Versuch:
Um zu verallgemeinern:
Wenn Sie E6 nicht ausführen, können Sie auch Folgendes tun:
Dies scheint etwas prägnanter zu sein als die vorherigen Antworten.
https://repl.it/@abalter/reusable-JS-template-literal
quelle
Im Allgemeinen bin ich gegen das Böse
eval()
, aber in diesem Fall macht es Sinn:Wenn Sie dann die Werte ändern und eval () erneut aufrufen, erhalten Sie das neue Ergebnis:
Wenn Sie es in einer Funktion wollen, dann kann es so geschrieben werden:
quelle
eval
.eval()
expliziten Aufruf erstellt wird, ist genau das gleiche wieeval()
, daher hat es keinen Vorteil, da der Code nur schwerer zu lesen ist.populate
Funktion den Code nicht dynamisch erstellt, sollte sie nichteval
mit all ihren Nachteilen verwendet werden.function populate(a,b) { return `${a}.${b}`; }
dieAKTUALISIERT: Die folgende Antwort ist auf einzelne Variablennamen beschränkt, daher sind Vorlagen wie:
'Result ${a+b}'
für diesen Fall nicht gültig. Sie können jedoch immer mit den Vorlagenwerten spielen:URSPRÜNGLICHE ANTWORT:
Basierend auf den vorherigen Antworten, aber Schaffung einer "freundlicheren" Dienstprogrammfunktion:
Sie können es wie folgt aufrufen:
Und die resultierende Zeichenfolge sollte sein:
quelle
`Result: ${a+b}`
Wenn Sie nach etwas ziemlich Einfachem suchen (nur feste Variablenfelder, keine Berechnungen, Bedingungen…), das aber auch clientseitig in Browsern ohne Unterstützung für Vorlagenzeichenfolgen wie IE 8,9,10,11 funktioniert …
Auf geht's:
quelle
Ich war verärgert über die zusätzliche Redundanz, die
this.
jedes Mal beim Tippen erforderlich ist , und fügte daher Regex hinzu, um Variablen.a
nach Belieben zu erweiternthis.a
.Lösung:
Verwendung als solche:
quelle
Ich veröffentliche nur ein npm-Paket, das diesen Job einfach erledigen kann. Tief inspiriert von dieser Antwort .
Das Gerät ist tödlich einfach. Ich wünschte, es würde dir gefallen.
quelle
Sie können die Inline-Pfeilfunktion wie folgt verwenden, Definition:
Verwendung:
quelle
Laufzeitvorlagenzeichenfolge
Prüfung
quelle
quelle