我已经在此处将其提出给Moustache规范:
我是Moustache的新手。
许多模板语言(例如Django / Jinja)将使您像这样扩展“父”模板...
<html><head></head>
<body>
{% block content %}{% endblock %}
</body>
</html>
{% extends "base.html" %}
{% block content %}<h1>Foobar!</h1>{% endblock %}
<html><head></head>
<body>
<h1>Foobar!</h1>
</body>
</html>
我知道小胡子的partials(例如{{>content}}
),但是这些似乎只是includes。
Mustache是否存在模板扩展名?否则,至少存在某种设计模式可以有效地将includes转换为模板扩展等效项。
我最近发现自己是在同一条船上,除了我来自玛科背景。
小胡子不允许模板扩展/继承,但是我知道有一些可用的选项。
您可以使用局部变量:
{{>header}}
Hello {{name}}
{{>footer}}
您可以将模板预处理功能注入需要从其他页面继承的每个模板的上下文中:
{{#extendBase}}
Hello {{name}}
{{/extendBase}}
哈希:
{
"name": "Walden",
"extendBase": function() {
return function(text) {
return "<html><head></head>" + render(text) + "</body></html>"
}
}
}
将所需的HTML附加并附加到控制器中的相关页面。
具有布局模板ala:
{{>header}}
{{{body}}}
{{>footer}}
并在控制器中渲染主体,将其作为名为body
的变量传递到布局模板。
实现模板继承,在加载模板的代码中,必须注意。
但是,我不会使用三重胡须,因为我不希望未转义的HTML出现在任何地方,在我看来这太冒险了。
如果其他人对这个问题有更好的解决方案,我也很想听听,因为我还没有朝这些方向中的任何一个尝试。
我已经在此处将其提出给Moustache规范:
当前mustache.java,hogan.js和phly_mustache支持模板继承。
您可以使用包含HTML的变量。像{{{variable}}}
这样的“三重胡子”将返回未转义的HTML。它与模板扩展名不完全相同,但是您可以呈现frontpage-content.html
content
变量中,该变量将传递给base.html((我在frontpage.html文件名中添加了[[-content
,期望这样的命名模式将有助于使文件名易于管理。)]如果您真的想要模板扩展,那么您可能希望使用为此功能构建的库,供您选择的语言/框架使用。
https://github.com/bobthecow/mustache.php/wiki/BLOCKS-pragma
您可以从文件Mustache / Engine.php中找出当前版本,并搜索包含以下内容的行:
class Mustache_Engine
{
const VERSION = '2.8.0';
...
我现在正在使用Python进行操作(注意,我是Mako的创建者),添加一个动态环境来捕获各部分似乎是对的,尽管我需要对此进行大量测试更多。基本上,我们使用lambda,其中前缀“ https://github.com/mustache/spec/issues/38中讨论的语法),前缀“ $”表示“这是一个继承的部分”。
import pystache class NameSpace(object): def __init__(self, renderer, vars_={}): self.renderer = renderer self._content = {} self.vars = vars_ def add_content(self, name, value): self._content[name] = value def __getattr__(self, key): if key in self.vars: # regular symbol in the vars dictionary return self.vars[key] elif key.startswith("<"): # an "inherit from this template" directive name = key[1:] return inheritor(self, name) elif key.startswith("$"): # a "here's a replaceable section" directive name = key[1:] if name in self._content: # if we have this section collected, return the rendered # version return sub_renderer(self, name) else: # else render it here and collect it return collector(self, name) else: # unknown key. raise AttributeError(key) def sub_renderer(namespace, key): def go(): def render(nested): return namespace._content[key] return render return go def collector(namespace, key): def go(): def render(nested): content = namespace.renderer.render(nested, namespace) namespace.add_content(key, content) return content return render return go def inheritor(namespace, name): def go(): def render(nested): namespace.renderer.render(nested, namespace) return namespace.renderer.render_name(name, namespace) return render return go
所以这是一些模板。 base.mustache:
<html> {{#$header}} default header {{/$header}} {{#$body}} default body {{/$body}} {{#$footer}} default footer, using {{local key}} {{/$footer}} </html>
hello.mustache:
{{#<base}} {{#$header}} new header {{/$header}} {{#$body}} new body, with {{local key}} {{/$body}} {{/<base}}
然后再玩三个层次的subhello.mustache:
{{#<hello}} {{#$footer}} im some new footer {{/$footer}} {{/<hello}}
像这样渲染hello.mustache:
renderer = pystache.Renderer(search_dirs=["./templates/"]) print renderer.render_name("hello", NameSpace(renderer, {"local key": "some local key"}))
输出:
<html> new header new body, with some local key default footer, using some local key </html>
呈现subhello.mustache:
print renderer.render_name("subhello", NameSpace(renderer, {"local key": "some local key"}))
输出:
<html> new header new body, with some local key im some new footer </html>
我刚刚在二十分钟内编写了这个,过去我只使用过handlebars.js一点,而现在只是第一次使用pystache,所以整个“胡子”想法对我来说还不是很深。但这似乎可行吗?如果您对仅服务器端的代码感到满意,请使用Django建模Nun is a Mustache-like templating system with extends functionality via its 'template overrides' feature。但是,尽管可以使用,但不再由其作者维护。在node.js中,您可以使用express-handlebars或hogan-express来设置胡子模板的布局,但是它们做事的方式不同,因为它们都不是在模板本身上设置布局,而是在您的模板中注册了布局应用代码。我写了一个简短的代码来启用扩展和创建布局。。[如果您不想复制/粘贴页眉/页脚,或者不想在所有管理子部分重复菜单栏,每次呈现页面/视图时,您只需要使用以下函数:可以用作utils模块的以下类的
build
:
class MustacheLayout { constructor() { if (!MustacheLayout.instance) { MustacheLayout.instance = this; } return MustacheLayout.instance; } async build(...layers) { let previousLayer = ''; let combinedLayout = ''; for (const layer of layers) { const { name: layerName } = layer; let { data: layerData } = layer; if (!layerData) layerData = {}; layerData.child = previousLayer; combinedLayout = await this.renderHtml(layerName, layerData); previousLayer = combinedLayout; } return combinedLayout; } renderHtml(viewName, data) { return new Promise((resolve, reject) => { this.app.render(viewName, data, (error, html) => { if (error) reject(error); resolve(html); }); }); } setExpressApp(expressApp) { this.app = expressApp; } } module.exports = new MustacheLayout();
//import the class const mustacheLayout = require('') //
const app = express();;
mustacheLayout.setExpressApp(app);
控制器
警告:-从最小的布局到最大的布局(base.html),您都需要遵守顺序-数据属性应在视图中命名为
const layout = require('mustache-layout'); router.get('/edit', async (_, res) => { const user = 'admin' const html = await layout.build( { name: 'admin/edition/editor.view.html', data: { user } }, { name:'layout/base.view.html' } ) return res.send(html); });
查看在此处使用您传递的数据
您需要在布局视图页面中使用关键字警告
child
。不要忘记三括号[{{{}}}
<!-- ditor.view.html --> <div> {{ user }} </div>
<!-- base.view.html --> <!DOCTYPE html> <html lang="en"> <body> {{ > layout/header.view }} <div class="main"> <div class="layout-content"> {{{ child }}} </div> </div> {{ > layout/footer.view }} </body> </html>
如果需要此代码的软件包版本,请检查mustache-layout-s
我已经在此处将其提出给Moustache规范:
您可以使用包含HTML的变量。像{{{variable}}}
这样的“三重胡子”将返回未转义的HTML。它与模板扩展名不完全相同,但是您可以呈现frontpage-content.html