tl; dr: Czy możliwe jest utworzenie literału szablonu wielokrotnego użytku?
Próbowałem użyć literałów szablonów, ale wydaje mi się, że po prostu tego nie rozumiem i teraz jestem sfrustrowany. To znaczy, myślę, że to rozumiem, ale „to” nie powinno być tym, jak to działa ani jak powinno. Powinno być inaczej.
Wszystkie przykłady, które widzę (nawet otagowane szablony) wymagają, aby „podstawienia” były wykonywane w czasie deklaracji, a nie w czasie wykonywania, co wydaje mi się całkowicie bezużyteczne dla szablonu. Może jestem szalony, ale „szablon” to dla mnie dokument, który zawiera tokeny, które są podstawiane, gdy go używasz, a nie kiedy go tworzysz, w przeciwnym razie jest to po prostu dokument (tj. Ciąg znaków). Szablon jest przechowywany z tokenami jako tokenami i te tokeny są oceniane, kiedy ... oceniasz go.
Wszyscy cytują okropny przykład podobny do:
var a = 'asd';
return `Worthless ${a}!`
To miłe, ale jeśli już wiem a
, po prostu return 'Worthless asd'
lub return 'Worthless '+a
. Jaki jest sens? Poważnie. Dobra, chodzi o lenistwo; mniej plusów, większa czytelność. Wspaniały. Ale to nie jest szablon! Nie IMHO. A MHO to wszystko, co się liczy! Problem, IMHO, polega na tym, że szablon jest oceniany po zadeklarowaniu, więc jeśli to zrobisz, IMHO:
var tpl = `My ${expletive} template`;
function go() { return tpl; }
go(); // SPACE-TIME ENDS!
Ponieważ expletive
nie jest zadeklarowany, wyświetla coś takiego My undefined template
. Wspaniały. Właściwie przynajmniej w Chrome nie mogę nawet zadeklarować szablonu; zgłasza błąd, ponieważ expletive
nie jest zdefiniowany. Potrzebuję tego, aby móc dokonać zamiany po zadeklarowaniu szablonu:
var tpl = `My ${expletive} template`;
function go() { return tpl; }
var expletive = 'great';
go(); // My great template
Jednak nie widzę, jak to jest możliwe, ponieważ tak naprawdę nie są to szablony. Nawet jeśli mówisz, że powinienem używać tagów, nie, nie działają:
> 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...
To wszystko doprowadziło mnie do przekonania, że literały szablonów są strasznie błędnie nazwane i należy je nazwać tym, czym naprawdę są: heredocami . Wydaje mi się, że „dosłowna” część powinna mnie ostrzec (jak w, niezmienna)?
Czy coś mi brakuje? Czy istnieje (dobry) sposób na utworzenie literału szablonu wielokrotnego użytku?
Daję ci, wielokrotnego użytku literały szablonów :
> 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!
A oto naiwna funkcja „pomocnika” ...
function t(t) { return '`'+t.replace('{','${')+'`'; }
var template = t(`This is
my {expletive} reusable
template!`);
...zrobić to lepiej".
Jestem skłonny nazywać je szablonowymi guterałami ze względu na obszar, z którego wywołują zawirowania.
<strike>
tagu.Odpowiedzi:
Aby te literały działały jak inne silniki szablonów, potrzebny jest formularz pośredni.
Najlepszym sposobem na to jest użycie
Function
konstruktora.Podobnie jak w przypadku innych silników szablonów, możesz pobrać ten ciąg z innych miejsc, takich jak plik.
Podczas korzystania z tej metody mogą wystąpić problemy, na przykład tagi szablonów są trudne w użyciu, ale można je dodać, jeśli jesteś sprytny. Nie możesz również mieć wbudowanej logiki JavaScript z powodu późnej interpolacji. Można temu zaradzić, myśląc.
źródło
new Function(`return \`${template}\`;`)
Możesz umieścić ciąg szablonu w funkcji:
Możesz zrobić to samo z otagowanym szablonem:
Pomysł polega na tym, aby pozwolić parserowi szablonu oddzielić ciągi stałe od zmiennej „slots”, a następnie zwrócić funkcję, która za każdym razem łączy je z powrotem w oparciu o nowy zestaw wartości.
źródło
reusable
można by go zaimplementować, aby zwracał funkcję i używałbyś${0}
i${1}
wewnątrz literału zamiast${a}
i${b}
. Następnie możesz użyć tych wartości, aby odwołać się do argumentów funkcji, podobnie do tego, co robi Bergi w swoim ostatnim przykładzie: stackoverflow.com/a/22619256/218196 (lub wydaje mi się, że to w zasadzie to samo).expression`a + ${node}`
zbudować węzeł BinaryExpression z istniejącym węzłem ASTnode
. Wewnętrznie wstawiamy symbol zastępczy, aby wygenerować prawidłowy kod, analizujemy go jako AST i zastępujemy symbol zastępczy przekazaną wartością.Prawdopodobnie najczystszym sposobem na to są funkcje strzałkowe (ponieważ w tym momencie używamy już ES6)
... a dla otagowanych literałów szablonów:
Pozwala to również uniknąć użycia
eval()
lubFunction()
może powodować problemy z kompilatorami i powodować spowolnienie.źródło
myTag
aby zrobić coś. Na przykład użyj parametrów wejściowych jako klucza do buforowania danych wyjściowych.var reusable = (value: string) => `Value is ${value}`
.Odpowiedź 2019 :
Uwaga : biblioteka początkowo oczekiwała, że użytkownicy będą oczyszczać ciągi znaków, aby uniknąć XSS. Wersja 2 biblioteki nie wymaga już czyszczenia ciągów użytkownika (co i tak powinni zrobić twórcy stron internetowych), ponieważ
eval
całkowicie unika .es6-dynamic-template
Moduł na KMP to robi.W przeciwieństwie do obecnych odpowiedzi:
this
w ciągu szablonuUżycie jest proste. Użyj pojedynczych cudzysłowów, ponieważ ciąg szablonu zostanie rozwiązany później!
źródło
10 * 20 = ${10 * 20}
, może to być podobny format, ale nie jest to nawet zdalnie literały szablonu es6Tak, możesz to zrobić, analizując swój ciąg z szablonem jako JS przez
Function
(lubeval
) - ale nie jest to zalecane i zezwalaj na atak XSSPokaż fragment kodu
Zamiast tego możesz bezpiecznie wstawiać
obj
pola obiektów do szablonustr
w sposób dynamiczny w następujący sposóbPokaż fragment kodu
źródło
.*?
oznacza nie chciwy - jeśli usuniesz"?"
to snippet da zły wynikfunction 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
?Upraszczanie odpowiedzi udzielonej przez @metamorphasi;
źródło
eval
.var hosting
) TUTAJ .Jeśli nie chcesz korzystać z zamówionych parametrów lub kontekstu / nazw odwołać się do zmiennych w szablonie, na przykład
${0}
,${this.something}
lub${data.something}
można mieć funkcję szablonu, który dba o tworzenie zakresów dla Ciebie.Przykład, jak można nazwać taki szablon:
Funkcja szablonu:
Dziwactwo w tym przypadku polega na tym, że wystarczy przekazać funkcję (w przykładzie użyłem funkcji strzałki), która zwraca literał szablonu ES6. Myślę, że to drobny kompromis, aby uzyskać taką interpolację wielokrotnego użytku, której szukamy.
Tutaj jest na GitHub: https://github.com/Adelphos/ES6-Reuseable-Template
źródło
Object.values()
iObject.keys()
Krótka odpowiedź brzmi: użyj _.template w lodash
źródło
Może czegoś mi brakuje, bo moje rozwiązanie tego problemu wydaje mi się tak oczywiste, że jestem bardzo zaskoczony, że nikt nie napisał tego już w tak starym pytaniu.
Mam na to prawie jedną linijkę:
To wszystko. Kiedy chcę ponownie użyć szablonu i odroczyć rozstrzygnięcie podstawień, po prostu robię:
Zastosowanie tego tagu zwraca z powrotem a
'function'
(zamiast a'string'
), który ignoruje wszelkie parametry przekazane do literału. Następnie można go później wywołać z nowymi parametrami. Jeśli parametr nie ma odpowiedniego zastąpienia, staje się'undefined'
.Rozszerzona odpowiedź
Ten prosty kod jest funkcjonalny, ale jeśli potrzebujesz bardziej rozbudowanego zachowania, możesz zastosować tę samą logikę i masz nieskończone możliwości. Mógłbyś:
Możesz przechowywać oryginalne wartości przekazane do literału w konstrukcji i używać ich w kreatywny sposób podczas stosowania szablonu. Mogą stać się flagami, walidatorami typów, funkcjami itp. Oto przykład, w którym są używane jako wartości domyślne:
Następnie:
Zrób to, opakowując tę logikę w funkcję, która oczekuje jako argument funkcji niestandardowej, którą można zastosować w redukcji (podczas łączenia fragmentów literału szablonu) i zwraca nowy szablon z niestandardowym zachowaniem.
Wtedy możesz np. Napisać szablony, które automatycznie zmieniają wartość lub oczyszczają parametry podczas pisania osadzonego html, css, sql, bash ...
Za pomocą tego naiwnego (powtarzam, naiwnego! ) Szablonu sql możemy budować takie zapytania:
Zaakceptuj nazwane parametry do zastąpienia: Niezbyt trudne ćwiczenie oparte na tym, co zostało już podane. W tej innej odpowiedzi jest implementacja .
Spraw, aby zwracany obiekt zachowywał się jak
'string'
: Cóż, jest to kontrowersyjne, ale może prowadzić do interesujących wyników. Pokazane w tej innej odpowiedzi .Rozwiązywanie parametrów w globalnej przestrzeni nazw w miejscu wywołania:
Cóż, to co pokazał OP jest jego uzupełnienie, używając polecenia
, to znaczyevil
eval
. Można to zrobić bezeval
, po prostu przeszukując przekazaną nazwę zmiennej do obiektu globalnego (lub okna). Nie pokażę, jak to zrobić, bo mi się to nie podoba. Zamknięcia to właściwy wybór.źródło
To moja najlepsza próba:
Aby uogólnić:
Jeśli nie używasz E6, możesz również wykonać:
Wydaje się, że jest to nieco bardziej zwięzłe niż poprzednie odpowiedzi.
https://repl.it/@abalter/reusable-JS-template-literal
źródło
Generalnie jestem przeciwny używaniu zła
eval()
, ale w tym przypadku ma to sens:Następnie, jeśli zmienisz wartości i ponownie wywołasz eval (), otrzymasz nowy wynik:
Jeśli chcesz to w funkcji, możesz to zapisać w następujący sposób:
źródło
eval
.eval()
jawnego wywoływania, jest dokładnie tym samym, coeval()
, dlatego nie ma z tego żadnej korzyści, ponieważ utrudnia tylko odczytanie kodu.populate
funkcja nie buduje dynamicznie kodu, nie powinna używaćeval
wszystkich swoich wad.function populate(a,b) { return `${a}.${b}`; }
eval, nic nie dodajeAKTUALIZACJA: Poniższa odpowiedź jest ograniczona do nazw pojedynczych zmiennych, więc szablony takie jak:
'Result ${a+b}'
nie są poprawne w tym przypadku. Zawsze możesz jednak pobawić się wartościami szablonu:ORYGINALNA ODPOWIEDŹ:
Oparta na poprzednich odpowiedziach, ale tworząca bardziej „przyjazną” funkcję użytkową:
Możesz to wywołać tak jak:
Wynikowy ciąg powinien być:
źródło
`Result: ${a+b}`
Jeśli szukasz czegoś raczej prostego (tylko stałe pola zmiennych, bez obliczeń, warunków…), ale działa to również po stronie klienta w przeglądarkach bez obsługi ciągów szablonów, takich jak IE 8,9,10,11 …
No to ruszamy:
źródło
Byłem zły na dodatkowej redundancji potrzebna wpisywać
this.
za każdym razem, więc ja również dodaje regex aby rozwinąć zmiennych jak.a
dothis.a
.Rozwiązanie:
Użyj jako takiego:
źródło
Po prostu publikuję jeden pakiet npm, który może po prostu wykonać tę pracę. Głęboko zainspirowany tą odpowiedzią .
Jego narzędzie jest zabójczo proste. Szkoda, że ci się to nie spodoba.
źródło
możesz użyć funkcji strzałki wbudowanej w ten sposób, definicja:
stosowanie:
źródło
Ciąg szablonu środowiska uruchomieniowego
Test
źródło
źródło