可以通过在会话变量更改时重新渲染然后直接操作 DOM 来渲染不同的模板并将它们放置在容器模板中。然而,这并不像 Meteor 的方式。是否有处理 DOM 更新的惯用方式?
客户端.js
if (Meteor.isClient) {
var getContainerContents = function() {
console.info('get container contents');
var active = Session.get('active') == 'foo' ? 'foo' : 'bar';
return Meteor.render(Template[active]());
};
Template.foo.contents = function() {
console.info('foo contents');
return 'The foos.';
};
Template.bar.contents = function() {
console.info('bar contents');
return 'The bars.';
};
Meteor.startup(function() {
console.info('startup');
Meteor.autorun(function() {
console.info('autorun');
$('#container').html(getContainerContents());
});
});
}
客户端.html
<head>
<title>conditional templates</title>
</head>
<body>
{{> main }}
</body>
<template name="main">
<section id="container"></section>
</template>
<template name="foo">
<h2>Foos</h2>
{{ contents }}
</template>
<template name="bar">
<h2>Bars</h2>
{{ contents }}
</template>
更新:也可以为此目的使用模板助手。解决方案是从 template() 函数返回未渲染的字符串内容,并在 Handlebars 中将它们标记为安全,如下所示:
html
<template name="main">
{{ contents }}
</template>
js
var getContainerContents = function() {
console.info('get container contents');
var active = Session.get('active') == 'foo' ? 'foo' : 'bar';
return Template[active]();
};
Template.main.contents = function() {
return new Handlebars.SafeString(getContainerContents());
};
// Remove the startup and autorun code. Not necessary now.
有两个问题可能使它不太理想。
- 在主模板内呈现的任何嵌套模板也必须标记为 SafeString。否则内容将被 Handlebars 转义。这可能会导致一些膨胀,因为每个嵌套模板都需要 SafeString 代码。
- 通过将字符串标记为安全(即未转义),开发人员现在有责任记住在将任何可能不安全的字符串插入页面之前对其进行转义。您拥有的这些越多,就越有可能造成安全漏洞。(有关文档,请参见http://handlebarsjs.com/)
所以,在我看来,这个问题仍然悬而未决。但我会听从编辑的意见。