经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » JS/JS库/框架 » JavaScript » 查看文章
JS模板编译的实现详情
来源:jb51  时间:2022/7/19 19:04:48  对本文有异议

前言

编译是一种格式变成另一种格式的过程。编译会导致好的结果,比如书写简单的代码,编译出来复杂的代码;或者提高代码的使用性能

这里只聊聊模板编译。

模板编译的简单实现

写一个最简单的模板

  1. <p>Hello, {{name}}!</p>

这个模板用数据{name: "world"}渲染后的结果是:

  1. <p>Hello, world!</p>

解决方法:最简单的方案,正则替换就行了

  1. const compile = function(template, data) {
  2. return template.replace(/{{(.+?)}}/g, (match, key) => data[key])
  3. }
  4.  
  5. const template = "<p>Hello, I'm {{name}}! {{age}} years old!</p>"
  6. const data = {
  7. name: "hayes",
  8. age: 18
  9. }
  10. const result = compile(template, data)
  11. console.log(result); // <p>Hello, I'm hayes! 18 years old!</p>

缺点很明显,除了正则替换字段,其他啥都干不了,

来看看简单的嵌套需求:

模板:

  1. <p>Hello, I'm {{user.name}}! {{user.age}} years old!</p>

渲染数据;

  1. const data = {
  2. user: {
  3. name: "hayes",
  4. age: 18
  5. }
  6. }

现在再使用上面的方法,就失效了。还用正则的话,会很难做。因为需要做语法/词法分析,来看看大括号内写的是什么了。

模板编译

其实对于上述的模板,也可以使用如下方式来写:

  1. const compile = function(data) {
  2. return `<p>Hello, I'm ${data.name}! ${data.age} years old!</p>`
  3. }

好处:只需一次编译,之后再使用就只需要直接填充数据即可。而且也方便支持data.user.name这种形式。

工具:使用new Function生成函数

生成一个函数,传入x和 y,执行return x + y来获得求和的功能

  1. const fn = new Function("x", "y", "return x + y");

打印fn可以看到输出的内容如下:

  1. ? anonymous(x,y) {
  2. return x + y
  3. }

1、构建模板生成函数

传入模板字符串,通过new Function方式返回一个新函数。新函数接收一个obj对象

  1. const compile = function(template) {
  2. // 模板字符串
  3. let result = "";
  4. // ...
  5. return new Function("obj", result);
  6. }

2、正则替换

{{xxx}}找出来,替换为obj.xxx

  1. const compile2 = function(template) {
  2. // 模板字符串
  3. let result = template.replace(/{{(.+?)}}/g, (match, key) => {
  4. return `obj.${key}`
  5. });
  6. result = `return "${result}"`;
  7. return new Function("obj", result);
  8. }
  9. const template2 = "<p>Hello, I'm {{user.name}}! {{user.age}} years old!</p>"
  10. const render2 = compile2(template2)
  11. console.log(render2);

此时,函数打印如下:

  1. ? anonymous(obj
  2. ) {
  3. return "<p>Hello, I'm obj.user.name! obj.user.age years old!</p>"
  4. }

我们需要把字符串中的obj.user.nameobj.user.age变成动态的。

修改一下正则

  1. const compile2 = function(template) {
  2. // 模板字符串
  3. let result = template.replace(/{{(.+?)}}/g, (match, key) => {
  4. return `" + obj.${key} + "` // 前后添上加号
  5. });
  6. result = `return "${result}"`;
  7. return new Function("obj", result);
  8. }
  9. const template2 = "<p>Hello, I'm {{user.name}}! {{user.age}} years old!</p>"
  10. const render2 = compile2(template2)
  11. console.log(render2);

再来看看函数的打印:

  1. ? anonymous(obj
  2. ) {
  3. return "<p>Hello, I'm " + obj.user.name + "! " + obj.user.age + " years old!</p>"
  4. }

最终代码:

  1. const compile = function(template) {
  2. // 模板字符串
  3. let result = template.replace(/{{(.+?)}}/g, (match, key) => {
  4. return `" + obj.${key} + "`
  5. });
  6. result = `return "${result}"`;
  7. return new Function("obj", result);
  8. }
  9. const template = "<p>Hello, I'm {{user.name}}! {{user.age}} years old!</p>"
  10. const render = compile(template)
  11.  
  12. const data = {
  13. user: {
  14. name: "hayes",
  15. age: 18
  16. }
  17. }
  18. const result = render(data)
  19. console.log(result); // <p>Hello, I'm hayes! 18 years old!</p>

渲染结果:

  1. "<p>Hello, I'm hayes! 18 years old!</p>"

到此这篇关于JS模板编译的实现详情的文章就介绍到这了,更多相关JS模板编译 内容请搜索w3xue以前的文章或继续浏览下面的相关文章希望大家以后多多支持w3xue!

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号