8

所以假设我正在存储<div>{{name}}</div><div>{{age}}</div>在我的数据库中。然后我想获取第一个 HTML 字符串并将其呈现在一个模板中——它只{{> template1}}呈现第一个字符串,其中包含{{name}}把手。然后我想给那个新生成的模板/html数据,这样它就可以用name数据库中的实际值填充把手,这样我们就可以得到<div>John</div>. 我试过做

<template name="firstTemplate">
    {{#with dataGetter}}
        {{> template1}}
    {{/with}}
</template>

其中 template1 定义为

<template name="template1">
    {{{templateInfo}}}
</template>

而 templateInfo 是从数据库中返回前面提到的带有把手的 html 字符串的助手。

dataGetter 就是这样(只是一个例子,我正在使用不同命名的集合)

Template.firstTemplate.dataGetter = function() {
    return Users.findOne({_id: Session.get("userID")});
}

我无法填充 {{name}}。我已经尝试了几种不同的方法,但似乎 Meteor 不明白字符串中的把手需要用数据进行评估。我在 0.7.0 上,所以没有 Blaze,由于我正在使用其他软件包,我目前无法升级,它们目前还没有 0.8+ 版本支持。任何关于我如何让它发挥作用的想法都非常感谢。

4

6 回答 6

9

在 1.0 中,上述方法均无效。我让它与客户端代码中定义的以下函数一起工作。关键是将选项 { isTemplate: true} 传递给编译函数。

var compileTemplate = function(name, html_text) {
  try {
    var compiled = SpacebarsCompiler.compile(html_text, { isTemplate:true });
      var renderer = eval(compiled);
      console.log('redered:',renderer);
      //Template[name] = new Template(name,renderer);
      UI.Template.__define__(name, renderer);
  } catch (err){
    console.log('Error compiling template:' + html_text);
    console.log(err.message);
  }
};

你可以在客户端上用这样的东西打电话:

compileTemplate('faceplate', '<span>Hello!!!!!!{{_id}}</span>');

这将在您的 html 中使用 UI 动态呈现

{{> Template.dynamic template='faceplate'}}

于 2014-11-14T05:43:15.650 回答
8

您实际上可以使用空格键编译器自己将字符串编译为模板。您只需将meteor add spacebars-compiler其添加到您的项目中。

在使用 0.8.x 的项目中

var compiled = Spacebars.compile("<div>{{name}}</div> and <div>{{age}}</div>");
var rendered = eval(compiled);

Template["dynamicTemplate"] = UI.Component.extend({
  kind: "dynamicTemplate",
  render: rendered
});

在使用 0.9.x 的项目中

var compiled = SpacebarsCompiler.compile("<div>{{name}}</div> and <div>{{age}}</div>");
var renderer = eval(compiled);

Template["dynamicTemplate"] = Template.__create__("Template.dynamicTemplate", rendered);
于 2014-05-02T17:05:59.177 回答
3

按照@user3354036 的回答:

var compileTemplate = function(name, html_text) {
  try {
    var compiled = SpacebarsCompiler.compile(html_text, { isTemplate:true }),
        renderer = eval(compiled);

    console.log('redered:',renderer);
    //Template[name] = new Template(name,renderer);
    UI.Template.__define__(name, renderer);
  } catch (err) {
    console.log('Error compiling template:' + html_text);
    console.log(err.message);
  }
};

1) 在你的 HTML 中添加这个

 {{> Template.dynamic template=template}}

2) 调用compileTemplate 方法。

compileTemplate('faceplate', '<span>Hello!!!!!!{{_id}}</span>');
Session.set('templateName','faceplate');

将模板名称保存在 Session 变量中。下一点将解释这一点的重要性。

3) 编写一个帮助函数来返回模板名称。我已经使用 Session 变量来做到这一点。如果您在单击事件上添加动态内容或父模板已经呈现,这很重要。否则你永远不会看到动态模板被渲染。

'template' : function() {
  return Session.get('templateName');
}

4) 写这个是父模板的渲染方法。这是为了重置 Session 变量。

Session.set('templateName','');

这对我有用。希望它可以帮助某人。

于 2016-02-25T11:29:43.040 回答
1

如果您需要动态编译 复杂的模板,我会建议 Kelly's answer。

否则,您有两种选择:

  1. 创建每个模板变体,然后动态选择正确的模板:

    例如,创建您的模板

    <template name="displayName">{{name}}</template>
    <template name="displayAge">{{age}}</template>
    

    然后动态地包含它们

    {{> Template.dynamic template=templateName}}
    

    返回或templateName返回的助手在哪里"age""name"

  2. 如果您的模板很简单,只需自己执行替换即可。您可以使用Spacebars.SafeString返回 HTML。

    function simpleTemplate(template, values){
          return template.replace(/{{\w+}}/g, function(sub) {
              var p = sub.substr(2,sub.length-4);
              if(values[p] != null) { return _.escape(values[p]); }
              else { return ""; }
          })
    }
    Template.template1.helpers({
      templateInfo: function(){
          // In this context this/self refers to the "user" data
          var templateText = getTemplateString();
          return Spacebars.SafeString(
              simpleTemplate(templateText, this)
          );
      }
    
于 2014-05-01T23:52:06.833 回答
1

幸运的是,整个问题和任何其他类似问题的解决方案都以Blaze 包的形式提供给 Meteor API ,这是使反应式模板成为可能的核心 Meteor 包。如果您查看链接的文档,Blaze 包提供了一长串函数,这些函数允许以编程方式创建、呈现和删除反应性和非反应性内容的各种解决方案。

为了解决上述问题,您需要做以下事情:

首先,预测需要为应用程序动态呈现的不同 HTML 块。在这种情况下,这些块将是<div>{{name}}</div>and <div>{{age}}</div>,但它们实际上可以是任何有效的 HTML(尽管它还不是公共 API 的一部分,但未来开发人员将有更多选择以更动态的方式定义此内容,如文档中所述)您可以将它们放入小的模板定义中,如下所示:

<template name="nameDiv">
    <div>{{name}}</div>
</template>

<template name="ageDiv">
    <div>{{age}}</div>
</template>

其次,firstTemplate需要更改模板的定义以包含可以以编程方式引用的 HTML 节点,如下所示:

<template name="firstTemplate">
    <div></div>
</template>

然后,您需要为firstTemplate模板定义逻辑,利用 Blaze 包提供的一些功能,即Blaze.WithBlaze.renderBlaze.remove(尽管您可以更改以下逻辑并利用Blaze.renderWithData函数;这完全取决于您对如何定义逻辑的个人偏好 - 为了解释起见,我在下面仅提供一种可能的解决方案)。

Template.firstTemplate.onRendered(function() {
    var dataContext = Template.currentData();
    var unrenderedView = Blaze.With(dataContext, function() {
        // Define some logic to determine if name/age template should be rendered
        // Return either Template.nameDiv or Template.ageDiv
    });
    var currentTemplate = Template.instance();
    var renderedView = Blaze.render(unrenderedView, currentTemplate.firstNode);

    currentTemplate.renderedView = renderedView;
});

Template.firstTemplate.onDestroyed(function() {
    var renderedView = Template.instance().renderedView;
    Blaze.remove(renderedView);
});

因此,我们在onRendered您的模板函数中所做的firstTemplate是动态确定我们想要呈现到页面上的哪些数据(在您的情况下是名称或年龄),并使用该Blaze.With()函数创建该模板的未呈现视图使用firstTemplate模板的数据上下文。然后,我们选择firstTemplate我们希望动态生成的内容包含在其中的模板元素节点,并将这两个对象传递给Meteor.render()函数,该函数将未渲染的视图渲染到页面上,指定的元素节点作为渲染内容的父节点。

如果您阅读该Blaze.render()函数的详细信息,您将看到此渲染的内容将保持反应状态,直到使用该Blaze.remove()函数删除渲染的视图,或者从 DOM 中删除指定的父节点。在上面的示例中,我将引用从调用中收到的渲染视图Blaze.render()并将其直接保存在模板对象上。我这样做是为了当模板本身被销毁时,我可以在onDestroyed()回调函数中手动删除渲染的视图,并确保它确实被销毁了。

于 2015-08-18T01:56:21.267 回答
1

一种非常简单的方法是在 onRendered 事件中包含对全局 Blaze 对象的调用。

Blaze.renderWithData(Template[template_name], data ,document.getElementById(template_id))
于 2016-01-26T21:07:30.967 回答