在 Meteor.js 中动态加载模板

IT技术 javascript meteor
2021-03-16 13:10:08

我希望能够在不显式指定模板的情况下动态加载模板。

举个例子:

<template name="foo">
</template>

其中 'foo' 是模板,我希望能够通过调用某种方法动态加载它:

Meteor.render(Meteor.loadTemplate('foo'));

这可能吗?

6个回答

从 Meteor 0.9.4 - 1.0 开始,以下是如何动态渲染模板。在撰写本文时,所有其他答案都已过时。

假设您正在编辑一堆记录,或创建一个新记录,并且想要根据某些 Session 变量呈现update模板或new模板。

有两种方法可以做到这一点:

1) 这是Meteor 0.9.4 或更新版本官方推荐的方法- 它使用Template.dynamic

<template name="records">
  {{> Template.dynamic template=whichOne}}
</template>

<template name="recordUpdate">
  ...
</template>

<template name="recordNew">
  ...
</template>

Template.records.helpers({
  whichOne: function () {
    return Session.get('edit') ? 'recordUpdate' : 'recordNew'
    // note that we return a string - per http://docs.meteor.com/#template_dynamic
  }
});

2) 这适用于各种 Meteor 版本,但不正式推荐,因为不清楚模板是动态选择的:

<template name="records">
  {{> whichOne}}
</template>

{{! Note how "whichOne" is indistinguishable from a constant template name... }}
{{  ...like "recordUpdate" or "recordNew" below. }}

<template name="recordUpdate">
  ...
</template>

<template name="recordNew">
  ...
</template>

Template.records.helpers({
  whichOne: function () {
    return Session.get('edit') ? Template.recordUpdate : Template.recordNew
    // note that we return a Template object, not a string
  }
});

要将数据上下文传递给模板,请使用:

{{> Template.dynamic template=whichOne data=myData}}
@Turbo @DanDascalescu :: 关于可选地传递数据的行,data=myData片段:是key=value吗?
2021-04-20 13:10:08
非常好 - +1 因为您花时间写了更新我们的当前信息,因为 Meteor 是“版本化”演变的。我发现自己在使用 #1 方法。收到调试报告后我很满意,因为错误是我所期望的,并且与我所看到的成千上万的调试报告相比并没有不成比例。然而,方法#2 返回了不太详细的报告,并且仍然存在一些错误——可能是因为(我不确定,但怀疑)当涉及“中间处理”时,它在过程之间“过于动态”。感谢您提供更新的信息。
2021-04-28 13:10:08
@Faron 参数名称特指数据,值将成为模板的 this 上下文。myData 是可在所选模板中访问的对象。
2021-04-29 13:10:08
这是现在最流行的答案,但我建议展示如何选择性地将数据传递到范围。{{> Template.dynamic template=whichOne data=myData}}
2021-04-30 13:10:08
@Faron:这是整个数据上下文。请参阅docs.meteor.com/#/full/template_dynamic
2021-05-07 13:10:08

Meteor 0.9.x 新 API

Dan Dascalescu 指出 Meteor 现在有内置的动态模板!这很好,因为您不需要包含在以前版本中看到的额外代码。

{{> Template.dynamic template=template [data=data] }}

对于 Meteor 0.8.x Legacy

没有数据的动态模板:鲍里斯·科托夫 (Boris Kotov) 更新的 Blaze (0.8.0) 答案在正确的轨道上(取自最新文档),但对我来说却无法正常工作。我得到了以下工作:

{{> dynamicTemplate name=myDynName}}

<template name="dynamicTemplate">
    {{#with chooseTemplate name}}
        {{> template}}
   {{/with}}
</template>

Template.dynamicTemplate.chooseTemplate = function (name) {
    return { template: Template[name] };
};

我希望有一个更简单的解决方案,但我需要将模板包装在 JSON 中,如图所示。也许这会帮助其他人继续前进。

带有数据的动态模板:如果您拥有并希望数据是动态的,请务必制作一个可以做出react的辅助方法。请务必在某处执行 Session.set() 以查看效果。

// Inside "myContainingTemplate"
{{> dynamicTemplateWithData name=myDynName data=myDataHelper}}

<template name="dynamicTemplateWithData">
    {{#with chooseTemplate name}}
        {{#with ../data}}
            {{> ..}}
        {{/with}}
    {{/with}}
</template>

Template.dynamicTemplateWithData.chooseTemplate = function (name) {
    return Template[name];
};

Template.myContainingTemplate.helpers({
    myDataHelper: function () {
        Session.get('myReactiveKey');
    }
});
与此同时,API 也发生了变化。现在推荐的方法是使用docs.meteor.com/#template_dynamic
2021-04-16 13:10:08

您已找到 Meteor.render,但您缺少的是模板加载。在文档中它提到您可以调用 Template.foo() 来返回模板的 HTML。

http://docs.meteor.com/#template_call

将它们放在一起,您可以使用括号访问访问模板 foo 或任何其他模板,以便:

var templateName = "foo";
var fragment = Meteor.render( function() {
    return Template[ templateName ](); // this calls the template and returns the HTML.
});

那么 fragment 就是你的 Reactive fragment,这样你的模板就可以继续接收实时更新。您的片段现在需要放置在网页中(我使用 jQuery,所以这个例子也是如此):

$("#htmlnode").html( fragment );

$("#htmlnode") 只是 DOM 中您希望呈现模板的节点。现在,您的网页中已呈现呈现的内容。

这对我有用,但有一些细微的变化。因为我已经用 div 标签包围了模板中的元素,所以使用上面的代码呈现了一个未定义的片段。调用 Meteor.render( Template[ templateName ] ) 解决了这个问题。
2021-04-19 13:10:08
以防万一有人对代码有问题,您可能需要在调用模板之前先使用“if (Template[templateName])”检查模板是否可访问。
2021-04-23 13:10:08
我希望这可以与返回 HTML 字符串而不是 documentFragment 一起使用,以便您可以让 Meteor 的 Spark 呈现模板,即在另一个模板中。有谁知道怎么做?将文档片段作为模板助手返回不起作用,并且返回在提供给 render() 的函数中生成的字符串。它拥有所有地标和标签。
2021-05-05 13:10:08
这个答案和评论已被 Meteor 0.9.4 废弃 - 请参阅我的答案github.com/meteor/meteor/issues/2836关于直接分配给Template.foo.
2021-05-05 13:10:08
非常正确戴夫。如果模板不存在,我倾向于向控制台打印一条消息,以便我立即知道我是否使用了错误的名称等。
2021-05-09 13:10:08

我就是这样做的,不需要jQuery:

已编辑

Template.mainContent.showContentFromRouter = function() {
    return Template[Meteor.Router.page()]();
};

在这种情况下,我使用的是 Meteor 路由器,并返回我选择的任何模板(从路由器),但您可以这样做:

Template.mainContent.showDynamicContent = function() {
    return Template['someTemplateYouveDefined']();
};
当我尝试此操作时,标记在页面上显示为字符串。你如何解决这个问题?
2021-04-24 13:10:08
这个方案的问题是模板在内存中一遍遍的生成,只要调用showDynamicContent函数。有没有办法从内存中删除模板?我通过渲染 1000 多个子模板并来回删除它们来测试这个
2021-04-24 13:10:08
这是非常过时的 - 请参阅我的回答github.com/meteor/meteor/issues/2836关于直接分配给Template.foo.
2021-04-28 13:10:08
您在模板中的 {{showContentFromRouter}} 事物周围添加额外的 {}。像这样:{{{showContentFromRouter}}}。此 HTML 转义字符串。@萨摩
2021-05-11 13:10:08
@frozeman,我不太明白你的意思。你能用我的解决方案测试它吗?-> #2 答案。或者告诉使用,如何测试它=)
2021-05-13 13:10:08

火焰更新:

https://github.com/meteor/meteor/wiki/Using-Blaze#templatefoo-is-not-a-function-and-does-not-return-a-string

使用给定的数据上下文动态呈现模板

老的:

{{dynamicTemplate name="templateName" data=dataContext}}

Template.foo.dynamicTemplate = function (opts) {
  return Template[opts.name](opts.data);
};

新:(值得注意的是,在 Blaze 中,包含或块助手的关键字参数被捆绑到一个对象中,该对象成为新的数据上下文)

{{> dynamicTemplate name="templateName" data=dataContext}}

<template name="dynamicTemplate">
  {{#with chooseTemplate name}}
    {{#with ../data}}  {{! original 'data' argument to DynamicTemplate}}
      {{> ..}}         {{! return value from chooseTemplate(name) }}
    {{/with}}
  {{/with}}
</template>

Template.dynamicTemplate.chooseTemplate = function (name) {
  return Template[name];
}

顺便说一句,我并没有真正玩过它,但这是我从新的 blaze 文档中获取的内容。所以我认为这应该是这样做的方式;)

这是过时的 - 请参阅我的回答github.com/meteor/meteor/issues/2836关于直接分配给Template.foo.
2021-04-23 13:10:08
克里斯蒂安,我将我的回答更新为新的 0.8.0 版本。
2021-04-26 13:10:08
是,对的。在这种情况下,Id 是模板的标识符或模板的名称。上下文变量是您放入模板中的内容。希望能帮助到你。
2021-04-29 13:10:08
您如何或在哪里设置 id 和上下文?
2021-05-09 13:10:08
你的上下文是什么意思?你有没有想过名字=“templateNAME”?
2021-05-10 13:10:08