handlebars 是一款优秀的模板引擎,其基本的使用方法如下:
const str = `My name is {{name}}, I'm {{age}} years old`
const data = {name: 'keliq', age: 10}
console.log(require('handlebars').compile(str)(data))
// 得到:My name is keliq, I'm 10 years old
内部究竟是如何实现的呢?其实只需要三步:
第一步:解析模板
解析模板的目的就是把下面的字符串:
My name is {{name}}, I'm {{age}} years old
变成下面的数组:
[ 'My name is ', '{{name}}', ", I'm ", '{{age}}', ' years old' ]
解析函数如下:
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
}
第二步:构造表达式
构造表达式就是把第一步得到的解析结果:
[ 'My name is ', '{{name}}', ", I'm ", '{{age}}', ' years old' ]
转换成下面的 JS 表达式:
""+"My name is "+data.name+", I'm "+data.age+" years old"
这一步的实现相对比较简单,就是拼字符串,代码如下:
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
}
第三步:创建渲染函数
我们在第二步已经得到了 JS 表达式,但本质上还是一个字符串而已:
""+"My name is "+data.name+", I'm "+data.age+" years old"
那如何执行呢?通过 new Function
动态创建函数可以做到这一点:
const compile = (tpl) => {
return new Function("data", "return " + compileToString(parse(tpl)))
}
这就实现 handlebars 的 compile 函数了,不妨运行一下看看:
console.log(compile(str)(data))
// My name is keliq, I'm 10 years old
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!