我的Web应用程序目前正在使用Tapestry 5.2.6。我想写一个具有以下要求的新功能:
我的计划是选择并实施一种模板语言,可以在服务器或客户端上进行同等评估。对于初始页面加载,我可以在服务器上呈现模板。对于后续更新,我可以将项目的viewmodel对象作为JSON传递给客户端,并在那里评估模板。
到目前为止一切顺利。问题在于,我所看到的模板语言都没有足够强大,能够为未来的发展做好准备。作为案例研究,请考虑以下因素:
似乎没有能力像这样进行“包装”转换:
# base template
{>widget}
<span class="content">Hello world</span>
{/widget}
# widget template
<div class="widget">
{>widget_body/}
</div>
# rendered output
<div class="widget">
<span class="content">Hello world</span>
</div>
请注意,包装的内容是从基本模板中获取的,并且小部件模板的输出在两侧都包围它。我知道用上述语言实现这一目标的唯一方法就是模板:
{>open_widget/}
{>widget_body/}
{>close_widget/}
这意味着每个组件的两个模板,一个开启器和一个更接近,都包含未关闭的标签。 (公平地说,灰尘可以使用块和内联部分来优雅地执行此操作,但由于内联部分是模板的全局部分,因此每个模板仅限一次使用窗口小部件。)
我对模板的疑问是:
答案 0 :(得分:1)
我不确定那里是否有任何你正在谈论的内容。我需要类似的东西,并认为编写一个简单的文本替换脚本比比较现有的解决方案和学习使用它更快。
这个脚本不是生产就绪的(应该进行更多测试,API很奇怪),但它应该让你知道一种方法。
以下是它的设置方式:
在文档中存储模板
模板文本存储在脚本标记中,其type
属性不是“text / javascript”。每个模板都有一个唯一的id属性。
<script id="some_template" type="text/plain">
a valid template
</script>
浏览器不应该呈现这些。允许使用任何字符(</script>
除外),并且不需要转义任何内容。
<强>占位符强>
占位符如下所示:{@some_identifier}
。
<script id="image_template" type="text/plain">
<a href="{@img_url}"><img src="{@img_url}"></a>
</script>
每个占位符都将替换为:
在另一个
中包含一个模板 @@
“pseudotag”包含当前模板中另一个模板的内容。
<script id="photo_template" type="text/plain">
<@@ image_template></@@>
<div class="photo-caption">{@caption}</div>
</script>
photo_template
包括image_template
。所有包含替换都在替换占位符之前发生,因此photo_template
具有{@img_url}
和{@caption}
个占位符。
包含替换占位符
这就是“包装”的来源。理想情况下,占位符几乎总是被其他模板中的内容替换,而不是在获取模板副本时传入的值。
<script id="missing_photo_template" type="text/plain">
<@@ photo_template>
<@ img_url>notfound.png</@>
</@@>
</script>
missing_photo_template
包含photo_template
,为{@img_url}
提供替换,因此missing_photo_template
只有{@caption}
占位符。
<强>的JavaScript 强>
API现在很糟糕,但主要名称空间at
基本上有两个函数txt
和node
。第一个获取模板的副本作为文本,第二个获取副本作为元素(这意味着它应该有一个根节点,与上面的一些示例不同)。
这是:
/**
Atrocious Templates
*/
var at = (function(){
var rTemplate = /<@@\s*(.*?)>((?:[\w\W](?!<@@))*?)<\/@@>/gm,
rOption = /<@\s*(.*?)>([\w\W]*?)<\/@>/gm,
rValue = /\{@(.*?)\}/g,
rTag = /<(\w+)/i,
rSpace = /\s+/,
templates = {},
doc = document.implementation.createHTMLDocument('');
/**
Inlcude inner templates.
@private
@param {string} m0
The full inclusion text.
@param {string} m1
The ID of the included template.
@param {string} m2
Values passed to included template.
@return {string}
*/
function includeTemplates(m0, m1, m2) {
var opts = {};
m2.replace(rOption, function(m0, m1, m2) { opts[m1] = m2; });
return txt(m1, opts, true);
}
/**
Get text contents of a template.
@private
@param {string} id
The ID of the template.
@return {string}
*/
function get(id) {
if (templates[id]) return templates[id];
var last, t = document.getElementById(id).innerHTML;
while (last != t && (last = t)) t = t.replace(rTemplate, includeTemplates);
return (templates[id] = t);
}
/**
Get a text copy of a template.
@param {string} id
The ID of the template.
@param {Object.<string|function ():string>} options
Properties of this object will replace placeholder tokens.
Each property can be either a string, or a function which
returns a string.
@param {boolean=} noStrip
By default, placeholders for which no replacement text is
found are removed. Setting this to `true` overrides that
behavior, leaving non-replaced placeholders intact.
@return {string}
*/
function txt(id, options, noStrip) {
if (!options) options = {};
return get(id).replace(rValue, function(m0, m1) {
var v = options[m1];
return noStrip && !v && m0 || v && (v.call ? v() : v) || '';
});
}
/**
Get a node copy of a template.
@param {string} id
The ID of the template.
@param {Object.<string|function ():string>} options
Properties of this object will replace placeholder tokens.
@return {string}
*/
function node(id, options) {
var text = txt(id, options),
root = text.match(rTag)[1];
doc.open; doc.write(text); doc.close();
return doc.getElementsByTagName(root)[0];
}
// exports
return { txt: txt, node: node };
}());
同样,我不建议你在生产中使用它,因为它没有经过多少测试(虽然看起来工作正常),但希望这会给你一些关于你想要的东西的想法。< / p>
答案 1 :(得分:0)
尝试查看handlebarjs.com - 我在服务器和客户端都使用它。
答案 2 :(得分:-1)
也许这个问题已经过时了,但是Mustache不支持 partials 吗?
http://mustache.github.io/mustache.5.html
...通过这种方式,您可能希望将partials视为包含或模板 扩张,即使它不是真的。
例如,此模板和部分:
<强> base.mustache 强>:
<h2>Names</h2> {{#names}} {{> user}} {{/names}}
<强> user.mustache 强>:
<strong>{{name}}</strong>
可以被认为是一个单一的扩展模板:
<h2>Names</h2> {{#names}} <strong>{{name}}</strong> {{/names}}