目录
- 模板引擎
- new Function('参数','函数体'); 动态创建函数体
- 模板渲染函数
- 编译过程
一、模板引擎
为了实现视图与业务逻辑的分离,无论MVP、MVVM、MVC那个V都会使用模板引擎。线面我们说说模板引擎的要求。
1) 需求
1.1) {{ }} 表达式
其实就是 将{{ }}中的值根据替换为表达式的结果。
模板 | 结果 | |
---|---|---|
<b>{{ name }}</b> | → | <b>tom</b> |
<b>{{ name.toUpperCase() }}</b> | → | <b>TOM</b> |
<b>{{ '[' + name + ']' }}</b> | → | <b>[tom]</b> |
1.2) 循环语句
{%arr.forEach(item => {%}
<li>{{item}}</li>
{%})%}
生成
<li>aaa</li>
<li>bbb</li>
1.3) 条件语句
{% if(isShow) { %} <b>{{ name }}</b> {% } %}
生成
<b>tom</b>
二、 new Function()动态创建函数体
需要一个我们不太常用的语法 new Function()用于动态创建函数体 比如
new Function('arg', 'console.log(arg + 1);');
// 相当于创建了一个匿名函数
function (arg) {
console.log(arg + 1);
}
三、模板渲染函数
模板渲染的功能大概可以归纳为两步:
- 编译模板为Generate函数
- 执行渲染函数
比如最简单的模板
<b>{{ name }}</b>
生成后的渲染函数
generate(obj){
let str = '';
with(obj){
str+=`<b>${name}</b>`}
return str;
}
执行generate结果
const ret = generate({name : 'tom'})
// 运行结果: <b>tom</b>
四、 编译过程
我们把编译过程其实就是通过正则表达式的匹配
1) 第一步 插值表达式处理
将{{ xxx }}表达式
转化为 ES6模板字符串 ${ xxx }
将
<b>{{ name }}</b>
转化为 "${name}"
let str = `<b>{{ name }}</b>`;
let templateStr = str.replace(/\{\{([^}]+)\}\}/g, function () {
let key = arguments[1].trim();
return "${" + key + "}";
});
console.log(templateStr); // "<b>${name}</b>"
2) 第二步 循环语句,分支语句处理
此处后续补充
五 简易模板引擎
function compile(str) {
return obj => str.replace(/{{(.*?)}}/g, (_, s) => Function('obj', `with(obj) {return ${s};}`)(obj));
}
参考
总结
- new Function('参数','函数体'); 动态创建函数体