这个是公司内部使用的一个模版引擎,主要应用在pc。
根据模版,返回一个js文件。大概是这个样子的js。
(function(N, undefined){ var PATH = 'http://core.pc.lietou-static.com/tpls/common/plugins/localdata/city.js'; if(!N || !N._tpls) return false; N._tpls[PATH] = N._tpls[PATH] ||{......}; })(window.NodeTpl);
其实也就是传入了全局的NodeTpl变量。并且给path赋值了。path赋值是模版引擎做的事情。
如果NodeTpl中的模版缓存中已经有了这个路径了,那就直接取得,不然就需要再定义个对象出来。这个对象要包含整个模版文件中的不同模版对象。每个都是个方法。
通常是通过main主模版方法,在里面可能会用到子模版的方法。。。
传给这些方法的有$data数据, 和guid(模版的id)。这里目前有个疑惑。。。
这个对象中有个template方法,在pc端根据不同浏览器确定是数组拼接还是字符串拼接,m端和以后就不需要这个了,直接字符串拼接就好。因为浏览器js引擎对字符串拼接做了优化,字符串更快。
这里除了guid,还用了dguid,是数据的id。
然后开始了css代码的处理,其实就是每个前面都加上了模版对应都guid,对js也进行了封装炒作,(怎么感觉做了很多不是模版引擎应该干的事情呢)
js添加的代码如下:
'(function(window, document, undefined){\n'); template.push(' var $ROOT = $("#'+ guid +'");\n'); template.push(' var $TPLS = NodeTpl._tpls["'+ PATH +'"];\n'); template.push(' var $DATA = NodeTpl._data["'+ dguid +'"];\n');
进行了封装,并且定义了三个变量,这三个变量用来作区分。
这个还有个require方法,可以用来获得子模版的内容。解析require之后的代码如下:
container.html($TPLS[\'view-hwgat\']($DATA, "'+ guid +'"));\n');
目前为止,这个模版引擎实现的功能如下:
1 解析出模版本身
2 对css进行加id处理
3 对js封装处理
4 要可以通过require方法引入子模版,m端跟其他插件方法冲突,应该会修改成其他名字。比如include
至此,模版要做的事情就明确了。
下面再看看模版引擎是怎么实现的。
从入口开始看起:
window[moduleName].render = function (html, data, callback) {
var path = this.rguid(),
that = this,
cache = that._tpls;
if (typeof data === 'function') { callback = data, data = {}; } (new Function(renderTools.templete(path, renderTools.precompile(html))))(); typeof callback === 'function' && typeof cache[path] === 'object' && typeof cache[path].main === 'function' && callback.call(that, cache[path].main(data)); return that; };
先看底下,如果有callback,以及模版缓存会给你一个对象,并且这个对象的main方法是个函数,其实我们解析出来正确的结果就是这个样子的。就调用来callback方法,传递给nodetpl对象,以及模版main方法渲染后的片段
再看如何生成对应的模版缓存对象。通过new Function方法。具体再看里面的renderTools.templete方法。
这个方法干什么用的,代码如下:
templete: function (path, tpl) { var html = "", tpls = []; .......... html += "(function(N, undefined){\n"; html += " var PATH = '" + path + "';\n"; html += " if(!N || !N._tpls) return false;\n"; html += " N._tpls[PATH] = N._tpls[PATH] ||\n{\n"; html += tpls.join(',\n'); html += '\n};'; html += "\n})(window.NodeTpl);"; return html; }
传给它的是我们的模版引擎renderid,以及对应的模版内容,里面可能有多个子模版。 然后分别进行解析,这里解析主要是生成方法,文件中的css,js,html处理都在precompile中完成了。最终返回的就是我们的js文件。
这个path最终怎么成路径,目前还没看出来。
这个tpl传进去的就已经是预编译之后的来,调用来precompile方法,里面又用到compile方法。主要就是对css,js, html都做来处理,算是主要内容。这个主要内容大体就是正则替换
艾马,这么一边写边分析,果然比直接看代码容易理解多了