摘要:写在前面模板的诞生是为了将显示与数据分离,模板技术多种多样,但其本质是将模板文件和数据通过模板引擎生成最终的代码。目前有着很多这种模板引擎,诸如的,,的。当然在用过这么多的模板引擎后,也有着自己实现一个简易模板引擎的冲动。
写在前面
模板的诞生是为了将显示与数据分离,模板技术多种多样,但其本质是将模板文件和数据通过模板引擎生成最终的HTML代码。目前有着很多这种模板引擎,诸如Node的ejs,jade,PHP的Smarty。当然在用过这么多的模板引擎后,也有着自己实现一个简易模板引擎的冲动。于是今天就实现了一个简单的模板引擎,这个模板引擎非常简单,并不会涉及到语法分析,词法分析等编译原理相关知识,做的仅仅是将模板的js代码执行。下面来和大家分享下:
实现模板引擎语法参照的是ejs:
<% js code %>
<%= 变量名 %>
看下需要实现的目标:
// 模板代码
下面来考虑下,其实形成上述的html的话,利用js拼接字符串就可以做到,那么对于模板来说,是不是可以将模板内的js代码转化为原生js代码从而来实现呢?没错,这个简单的模板引擎干的就是这个事情,就是将模板内的被<% %>包裹的js代码执行,从而将模板转为html。
但是,如何做呢?可以采用Function(参数名, 函数主体),虽说这个平时不怎么使用,但是在这个情况下是最好的选择,将模板内的js代码解析提取后当做参数传入到Function中:
/** * 将模板引擎转化为可用dom字符串 * * @param {String} tpl * @param {Object} data 数据对象,为键值对形式,键值为数据名 * @return {String} */ function tpl2dom (tpl, data) { var nbspRE = /s{2,}/g, quotRE = /"/g, main = ""; // 函数主体 function fn (d) { var i, keys = [], vals = []; for (i in d) { keys.push(i); // 参数名 vals.push(d[i]); // 参数对应的值 } return (new Function(keys, main)).apply(d, vals); } if (!main) { tpl = tpl.replace(//g, ">"); // 将<和>替换 var tpls = tpl.split("<%"), len = tpls.length; main = `var res = "${tpls[0].replace(nbspRE, "").replace(quotRE, """)}"; `; // res就是拼接的html字符串 for (var i = 1; i < len; i++) { var p = tpls[i].split("%>"); // 发现第一个字符为`=`号时,直接进行赋值操作 main += 0x3D === p[0].charCodeAt(0) ? ` res += ${p[0].substr(1)}`: ` ${p[0].replace(/ /g, "").trim()}`; main += ` res += "${p[p.length - 1] .replace(nbspRE, "") .replace(quotRE, """) .replace(/[ ]/g, "")}"`; } main += " return res;"; } return data ? fn(data) : fn(); }
利用tpl2dom函数可以得到html,那下面在写一个函数来将html转为dom节点。从下面的函数可以看出的就是,这个模板引擎所解析的模板,只能有一个dom根节点:
var cacheDiv = document.createElement("div"); /** * 将可用dom字符串转为dom节点 * * @param {String} str * @return {DOM} */ function str2dom (str) { cacheDiv.innerHTML = ""; cacheDiv.innerHTML = str; // 由此可看出,模板只能有一个根节点 return cacheDiv.childNodes[0]; }
到此为止,模板引擎就基本完成了,既然是仿照的ejs,那么在来完善下,比如img_tag:
// 注意,实现该函数需放到全局 function img_tag (url) { return `` }
完整代码请见github,当然这个模板引擎只是一个玩物,并不能用于生产,比如,根本没有考虑到渲染过程中出错时如何定位到具体位置等问题。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/80498.html
摘要:整个引擎实现只有不到行代码。不知道你有木有听说过一个基于的页面预处理器,叫做。最初我只是打算写一个的预处理器,不过后来扩展到了和,可以用来把代码转成和代码。最后一个改进可以使我们的模板引擎更为强大。 导读:AbsurdJS 作者写的一篇教程,一步步教你怎样用 Javascript 实现一个纯客户端的模板引擎。整个引擎实现只有不到 20 行代码。如果你能从头看到尾的话,还能有不少收获的。...
摘要:暂时没有指令和。当前模块内的组件可以使用来自根模块和当前模块的任何服务及组件,也可以使用被导入模块中导出的组件。作为一个前端菜鸡,还是在深知自己众多不足以及明白好记性不如烂笔头的道理下,多造轮子总归不会错的。 有个同事跟我说:需求还是不够多,都有时间造轮子了。。。 前言 这个轮子从18年4月22造到18年10月12日,本来就是看了一个文章讲前端框架的路由实现原理之后,想试着撸一个路由试...
摘要:要求不需要有控制流成分如循环条件等等,只要有变量替换功能即可级联的变量也可以展开被转义的的分隔符和不应该被渲染,分隔符与变量之间允许有空白字符例子,实现先写下函数的框架显然,要做的第一件事便是匹配模板中的占位符。 首发于我的博客 转载请注明出处 这是源于两年前,当我在做人生中第一个真正意义上的网站时遇到的一个问题 该网站采用前后端分离的方式,由后端的 REST 接口返回 JSON 数据...
摘要:模板通常用来定义显示的形式,能够使得数据展现更为丰富,而且容易维护。从模板引擎的实现上看,需要依赖编程语言的动态编译或者动态解释的特性,以简化实现和提高性能。本文就来实现一个简易的模板引擎,以展现的强大之处。 模板简介 模板通常是指嵌入了某种动态编程语言代码的文本,数据和模板通过某种形式的结合,可以变化出不同的结果。模板通常用来定义显示的形式,能够使得数据展现更为丰富,而且容易维护。...
阅读 1064·2021-10-08 10:04
阅读 3505·2021-08-05 10:01
阅读 2258·2019-08-30 11:04
阅读 1764·2019-08-29 15:29
阅读 771·2019-08-29 15:12
阅读 1654·2019-08-26 12:11
阅读 3096·2019-08-26 11:33
阅读 1150·2019-08-26 10:23