工作中使用前端模板引擎,如 artTemplate、jsRender,来替代拼接字符串。
可是直接把模板写在页面上会带来页面臃肿,模板无法重用,与 ASP.NET等后端语言语法冲突等问题。
所以将多个模板集成到一个静态文件就很有必要,同时还能利用静态文件的缓存特性。
最好还能实现按需加载,不执行渲染的话就不载入模板文件。
虽然有对应的工具可以将模板转为 javascript 代码存在 .js 文件中,但是 js 下的模板代码可读性太差,不考虑。
于是根据以上需求写了一个jQuery 插件 $.loadTemplates
(function (window, $) { var tplCache = {}, ENG_JSRENDER = 'jsRender', ENG_ARTTEMPLATE = 'artTemplate', //判定使用的是哪个模板引擎 //暂时支持jsRender 和 artTemplate tplEngine = ($.views && $.views.jsviews) ? ENG_JSRENDER : window.template ? ENG_ARTTEMPLATE : '', Template = function (tplFile, templateTag) { var loaded = false, callbacks = $.Callbacks(), _templates = {}; $.ajax(tplFile).done(function (data) { var scripts = $(data).filter(templateTag || 'script'); scripts.each(function () { var id = this.id; if (!id) return; //预编译并缓存编译后的模板 //编译的时候要给定 id ,这样才能支持子模板嵌套 switch (tplEngine) { case ENG_JSRENDER: { _templates[id] = $.templates(id, this.innerHTML).render[id]; break; } case ENG_ARTTEMPLATE: { _templates[id] = template.compile(id, this.innerHTML); break; } } }); loaded = true; //触发在文件载入完成前挂上的渲染事件 callbacks.fire(); }); this.render = function (tplId, json, helper) { var def = $.Deferred(), _render = function () { var html; switch (tplEngine) { case ENG_JSRENDER: { html = $.render[tplId](json, helper); break; } case ENG_ARTTEMPLATE: { if (helper) template.helper(helper); html = _templates[tplId](json); break; } } def.resolve(html); }; loaded ? _render() : callbacks.add(_render); return def.promise(); }; tplCache[tplCache] = this; }; $.extend({loadTemplates: function (tplFile, templateTag) { return tplCache[tplFile] || new Template(tplFile, templateTag); }}); })(window, jQuery);
var tpl = $.loadTemplates('template.html'); var json = {str:'this is test'}; var templateId = 'temp1'; tpl.render(templateId, json) .done(function(html){ $('body').html(html); });
存在的问题:
1. 由于使用了$.ajax 加载,所以模板文件的缓存在开发过程中可能会带来困扰。
2. 对于 'template.html' 和 './template.html' 无法识别为同一个静态文件。(前端 url 的同一性判断谁能给解下惑)