JS模板编译的实现详情
前言
编译是一种格式变成另一种格式的过程。编译会导致好的结果,比如书写简单的代码,编译出来复杂的代码;或者提高代码的使用性能。
这里只聊聊模板编译。
模板编译的简单实现
写一个最简单的模板
<p>Hello, {{name}}!</p>
这个模板用数据{name: "world"}
渲染后的结果是:
<p>Hello, world!</p>
解决方法:最简单的方案,正则替换就行了
const compile = function(template, data) {
return template.replace(/{{(.+?)}}/g, (match, key) => data[key])
}
const template = "<p>Hello, I'm {{name}}! {{age}} years old!</p>"
const data = {
name: "hayes",
age: 18
}
const result = compile(template, data)
console.log(result); // <p>Hello, I'm hayes! 18 years old!</p>
缺点很明显,除了正则替换字段,其他啥都干不了,
来看看简单的嵌套需求:
模板:
<p>Hello, I'm {{user.name}}! {{user.age}} years old!</p>
渲染数据;
const data = {
user: {
name: "hayes",
age: 18
}
}
现在再使用上面的方法,就失效了。还用正则的话,会很难做。因为需要做语法/词法分析,来看看大括号内写的是什么了。
模板编译
其实对于上述的模板,也可以使用如下方式来写:
const compile = function(data) {
return `<p>Hello, I'm ${data.name}! ${data.age} years old!</p>`
}
好处:只需一次编译,之后再使用就只需要直接填充数据即可。而且也方便支持data.user.name
这种形式。
工具:使用new Function
生成函数
生成一个函数,传入x
和 y
,执行return x + y
来获得求和的功能
const fn = new Function("x", "y", "return x + y");
打印fn
,可以看到输出的内容如下:
ƒ anonymous(x,y) {
return x + y
}
1、构建模板生成函数
传入模板字符串,通过new Function
方式返回一个新函数。新函数接收一个obj
对象
const compile = function(template) {
// 模板字符串
let result = "";
// ...
return new Function("obj", result);
}
2、正则替换
把{{xxx}}
找出来,替换为obj.xxx
const compile2 = function(template) {
// 模板字符串
let result = template.replace(/{{(.+?)}}/g, (match, key) => {
return `obj.${key}`
});
result = `return "${result}"`;
return new Function("obj", result);
}
const template2 = "<p>Hello, I'm {{user.name}}! {{user.age}} years old!</p>"
const render2 = compile2(template2)
console.log(render2);
此时,函数打印如下:
ƒ anonymous(obj
) {
return "<p>Hello, I'm obj.user.name! obj.user.age years old!</p>"
}
我们需要把字符串中的obj.user.name
和obj.user.age
变成动态的。
修改一下正则
const compile2 = function(template) {
// 模板字符串
let result = template.replace(/{{(.+?)}}/g, (match, key) => {
return `" + obj.${key} + "` // 前后添上加号
});
result = `return "${result}"`;
return new Function("obj", result);
}
const template2 = "<p>Hello, I'm {{user.name}}! {{user.age}} years old!</p>"
const render2 = compile2(template2)
console.log(render2);
再来看看函数的打印:
ƒ anonymous(obj
) {
return "<p>Hello, I'm " + obj.user.name + "! " + obj.user.age + " years old!</p>"
}
最终代码:
const compile = function(template) {
// 模板字符串
let result = template.replace(/{{(.+?)}}/g, (match, key) => {
return `" + obj.${key} + "`
});
result = `return "${result}"`;
return new Function("obj", result);
}
const template = "<p>Hello, I'm {{user.name}}! {{user.age}} years old!</p>"
const render = compile(template)
const data = {
user: {
name: "hayes",
age: 18
}
}
const result = render(data)
console.log(result); // <p>Hello, I'm hayes! 18 years old!</p>
渲染结果:
"<p>Hello, I'm hayes! 18 years old!</p>"
到此这篇关于JS模板编译的实现详情的文章就介绍到这了,更多相关JS模板编译 内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341