前端模板引擎 与 实现 (Handlebars)
1. 前端模板引擎的优势
1. 可维护性(后期改起来方便);
2. 可扩展性(想要增加功能,增加需求方便);
3.开发效率提高(程序逻辑组织更好,调试方便);
2. 前端模板引擎 Handlebars
使用过程
<script src="./js/handlebars-1.0.0.beta.6.js"></script>
3. 创建模板
在
<script type="text/x-handlebars-template" id="myTemplate">
<div class="demo">
<h1>{{name}}</h1>
<p>{{content}}</p>
</div>
</script>
4. 在 JS 代码中编译模板
// 获取模板
let tpl = document.getElementById("myTemplate").innerHTML;
// 预编译模板
let template = Handlebars.compile(tpl);
//匹配 json 数据内容
let html = template(data);
// 插入模板
document.getElementById("box").innerHTML = html;
3. 实现一个简单的前端模板引擎
我们再总结一下思路: 首先,使用模板引擎的格式来写这么一个模板,
然后经过一个函数处理,过程就是通过while循环,然后捕获到对应的变量的规则,将变量前的内容push到数组中,然后再使用数据进行替换,然后push到数组中,
接着通过字符串方法把前面的字符串截取,留下后面的字符串继续匹配,
最后,我们就可以通过join()方法来实现html的生成了,通过appendChild()就可以顺利插入数组了。
function Template(tpl) {
let fn, match;
// 用字符串形式编写代码, 代码换行使用\n, 然后使用
// new Function(code.join("\n")) 来执行代码
// _html 用来匹配 > < " & ' 等符号, 将其进行转换成 html 文本
// r 是最后要返回的
let code = ['var r=[];\nvar _html = function (str) { return str.replace(/&/g, \'&\').replace(/"/g, \'"\').replace(/\'/g, \''\').replace(/</g, \'<\').replace(/>/g, \'>\'); };']
// 可以使用 { xxx|safe } 这样的表达式表示xxx无需转义
let re = /\{\s*([a-zA-Z\.\_0-9()]+)(\s*\|\s*safe)?\s*\}/m;
// 向输出的代码模板中添加命令行, 使得传入的 text 中的 ' \n \r 等被转译成字符串形式, 使 code 可执行
let addLine = function (text) {
// 以字符串形式的代码, 将传入的 text 中的 ' \n
code.push('r.push(\'' + text.replace(/\'/g, '\\\'').replace(/\n/g, '\\n').replace(/\r/g, '\\r') + '\');');
};
// 将传入模板使用 re 正则进行匹配, 得到匹配位置索引与匹配内容, 匹配的是需要替换的变量
while (match = re.exec(tpl)) {
if (match.index > 0) {
// 将 变量前的内容 传入 code 中的 r 数组中
addLine(tpl.slice(0, match.index));
}
// 正则的第二个子表达式 也就是判断是否有 safe
if (match[2]) {
code.push("r.push(String(this." + match[1] + "));");
} else {
// 变成 html 文本
code.push('r.push(_html(String(this.' + match[1] + ')));');
}
// 裁剪传入模板, 准备匹配下一个{ 变量 }
tpl = tpl.substring(match.index + match[0].length);
}
addLine(tpl);
// 拼接 code 中定义的 r 并返回
code.push('return r.join("\\'");')
// 使用匿名函数执行 code 传给 fn
fn = new Function(code.join("\n"));
// 定义 render 函数
this.render = function (model) {
// 处理数据
return fn.apply(model);
};
}
// 使用
<script id="tpl" type="text/plain">
<p>Today: { date }</p>
<a href="/{ user.id|safe }">{ user.company }</a>
</script>
// 获取模板传入 Template
var tpl = new Template($('#tpl').html());
// 调用 render 函数传入数据
var s = tpl.render({
date: 20150101,
user: {
id: 'A-000&001',
company: 'AT&T'
}
});
// 传入数据
$('#other').html(s);
来源整理自:vue3js.cn 面试官系列



