前言
编译是一种格式变成另一种格式的过程。编译会导致好的结果,比如书写简单的代码,编译出来复杂的代码;或者提高代码的使用性能。
这里只聊聊模板编译。
模板编译的简单实现
写一个最简单的模板
Hello, {{name}}!
这个模板用数据{name: "world"}
渲染后的结果是:
Hello, world!
解决方法:最简单的方案,正则替换就行了
const compile = function(template, data) { return template.replace(/{{(.+?)}}/g, (match, key) => data[key]) } const template = "Hello, I'm {{name}}! {{age}} years old!
" const data = { name: "hayes", age: 18 } const result = compile(template, data) console.log(result); //Hello, I'm hayes! 18 years old!
缺点很明显,除了正则替换字段,其他啥都干不了,
来看看简单的嵌套需求:
模板:
Hello, I'm {{user.name}}! {{user.age}} years old!
渲染数据;
const data = { user: { name: "hayes", age: 18 } }
现在再使用上面的方法,就失效了。还用正则的话,会很难做。因为需要做语法/词法分析,来看看大括号内写的是什么了。
模板编译
其实对于上述的模板,也可以使用如下方式来写:
const compile = function(data) { return `Hello, I'm ${data.name}! ${data.age} years old!
` }
好处:只需一次编译,之后再使用就只需要直接填充数据即可。而且也方便支持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 = "Hello, I'm {{user.name}}! {{user.age}} years old!
" const render2 = compile2(template2) console.log(render2);
此时,函数打印如下:
ƒ anonymous(obj ) { return "Hello, I'm obj.user.name! obj.user.age years old!
" }
我们需要把字符串中的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 = "Hello, I'm {{user.name}}! {{user.age}} years old!
" const render2 = compile2(template2) console.log(render2);
再来看看函数的打印:
ƒ anonymous(obj ) { return "Hello, I'm " + obj.user.name + "! " + obj.user.age + " years old!
" }
最终代码:
const compile = function(template) { // 模板字符串 let result = template.replace(/{{(.+?)}}/g, (match, key) => { return `" + obj.${key} + "` }); result = `return "${result}"`; return new Function("obj", result); } const template = "Hello, I'm {{user.name}}! {{user.age}} years old!
" const render = compile(template) const data = { user: { name: "hayes", age: 18 } } const result = render(data) console.log(result); //Hello, I'm hayes! 18 years old!
渲染结果:
"Hello, I'm hayes! 18 years old!
"
到此这篇关于JS模板编译的实现详情的文章就介绍到这了,更多相关JS模板编译 内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!