Handlebars is an excellent templating engine. The basic usage is as follows:
const str = `My name is {{name}}, I'm {{age}} years old`
const data = {name: 'keliq'.age: 10}
console.log(require('handlebars').compile(str)(data))
// Get: My name is Keliq, I'm 10 years old
Copy the code
How does it work on the inside? There are only three steps:
Step 1: Parse the template
The purpose of parsing the template is to put the following strings:
My name is {{name}}, I'm {{age}} years old
Copy the code
Becomes the following array:
[ 'My name is '.'{{name}}'.", I'm ".'{{age}}'.' years old' ]
Copy the code
The analytic function is as follows:
var parse = (tpl) = > {
let result, firstPos
const arr = []
while (result = / {{(. *?) }}/g.exec(tpl)) {
firstPos = result.index
if(firstPos ! = =0) {
arr.push(tpl.substring(0, firstPos))
tpl = tpl.slice(firstPos)
}
arr.push(result[0])
tpl = tpl.slice(result[0].length)
}
if (tpl) arr.push(tpl)
return arr
}
Copy the code
Step 2: Construct the expression
Construct an expression by parsing the result of the first step:
[ 'My name is '.'{{name}}'.", I'm ".'{{age}}'.' years old' ]
Copy the code
Convert to the following JS expression:
""+"My name is "+data.name+", I'm "+data.age+" years old"
Copy the code
The implementation of this step is relatively simple, is the string, the code is as follows:
const compileToString = (tokens) = > {
let fnStr = ` "" `
tokens.map(t= > {
if (t.startsWith({{" ") && t.endsWith("}}")) {
fnStr += `+data.${t.split(/ / {{|}}).filter(Boolean) [0].trim()}`
} else {
fnStr += ` +"${t}"`}})return fnStr
}
Copy the code
Step 3: Create the render function
We already got the JS expression in step 2, but it’s essentially just a string:
""+"My name is "+data.name+", I'm "+data.age+" years old"
Copy the code
So how does that work? You can do this by creating functions dynamically with new Function:
const compile = (tpl) = > {
return new Function("data"."return " + compileToString(parse(tpl)))
}
Copy the code
This implements the compile function for Handlebars, so let’s run it:
console.log(compile(str)(data))
// My name is keliq, I'm 10 years old
Copy the code