(ab)템플릿 리터럴을 사용하여 간단한 JavaScript 템플릿 엔진

템플릿 인라인 문자열은 ES6 템플릿 리터럴을 사용하여 간단합니다.

const a = "hello"
const b = "world"

console.log(`${a} ${b}`)
//hello world


하지만 인라인할 수 없는 문자열(즉, 외부 소스에서 가져온 문자열)이 있는 경우에는 어떻게 해야 합니까?

최근에 이 목적으로 사용한 기능의 요지는 다음과 같습니다.

function tpl(str, props) {
    let names = Object.keys(props);
    let vals = Object.values(props);
    return new Function(...names, `return \`${str}\`;`)(...vals);
}


또는 (가독성이 약간 떨어짐) 한 줄짜리 버전:

const tpl = (str, props) => new Function(...Object.keys(props), `return \`${str}\`;`)(...Object.values(props))


예시:

console.log(tpl('${a} ${b}', {a: 'hello', b: 'world'}))
//hello world


설명



따라서 tpl라는 함수를 정의합니다.

function tpl(str, props) {
    let names = Object.keys(props);
    let vals = Object.values(props);
    return new Function(...names, `return \`${str}\`;`)(...vals);
}


처음 두 줄은 설명이 필요 없습니다. 전달된props 개체에서 키와 값을 추출하는 것뿐입니다.

마지막 줄에서는 문자열에서 함수를 동적으로 생성합니다. eval 대신 훨씬 안전한 대안인 Function 생성자를 사용하고 있습니다.

새로운(동적으로 생성된) 함수는 props 키의 이름 목록을 수신하고 전달된 동일한 문자열str을 반환하지만 백틱 문자로 구분됩니다(기본적으로 "외부"문자열을 인라인 템플릿 문자열로 바꿉니다). .

그런 다음 값 목록을 사용하여 새 함수를 호출하기만 하면 됩니다.

Function.call 대안



이름과 값을 추출하는 대신 다음과 같이 하여 작업을 단순화할 수 있습니다.

new Function(`return \`${str}\`;`).call(props)


하지만 ${this.a} 대신 ${a} 를 사용해야 합니다.

캐싱


Function 생성자를 호출할 때마다 함수 본문을 구문 분석해야 하지만(일부 오버헤드) str 값을 기반으로 일부 캐싱을 수행하는 것은 매우 쉽습니다.



참고: 이것은 BetterWays.dev wiki 의 위키 페이지 스냅샷입니다. 최신(더 나은 형식) 버전은 betterways.dev/simple-javascript-template-engine-by-ab-using-template-literals 에서 찾을 수 있습니다.

좋은 웹페이지 즐겨찾기