【问题标题】:How do I modify a template instance from an event handler in Meteor without Session?如何在没有 Session 的情况下从 Meteor 中的事件处理程序修改模板实例?
【发布时间】:2025-11-26 08:45:01
【问题描述】:

我正在尝试实现可扩展帖子 cmets 的层次结构,例如Quora,以便用户可以单击评论并查看任何回复。

为此,我想跟踪每个“评论”模板实例是否“扩展”,切换事件处理程序中的状态。

我可以使用整个堆栈会话变量(即每个评论一个)来做到这一点,但这似乎很笨拙,因为在任何给定页面上都有任意数量的 cmets。

下面是我目前正在尝试的内容。

JS:

Template.comment_item.events = {
    'click #comment-content': function( e, instance ) {
        this.expanded = true;  // also tried instance.data.expanded = true
    }
};

Template.comment_item.helpers({
    showChildComments: function(){
      this.expanded;
    }
});

HTML:

<template name="comment_item">
  <li class="comment comment-displayed" id="{{_id}}">
   <div class="comment-body">
      <div id="comment-content">
        <!-- some comment data here -->
      </div>
      {{#if showChildComments}}
      <ul class="comment-children comment-list">
          {{#each child_comments}}
            {{> comment_item}}
          {{/each}}
      </ul>
      {{/if}}
    </div>
  </li>
</template>

不幸的是,当我单步执行时,似乎在 showChildComments 助手中,模板实例看不到扩展变量。我确实在文档中注意到它说 instance.data 在事件映射中是只读的。

有没有办法直接在事件映射中修改模板实例?

【问题讨论】:

  • Session 有什么问题?您还可以以更传统的方式使用 JQuery,像 quora 一样直接访问 DOM

标签: javascript meteor


【解决方案1】:

您可以在它的 created 事件处理程序中为模板实例创建属性。并且您可以访问模板实例作为事件映射函数的第二个参数。

Template.comment_item.created = function() {
  this.showChildren = false;
};

Template.comment_item.events({
  'click .comment-content': function(event, template) {
    template.showChildren = true;
  }
});

但是:

  1. 您无法从模板帮助程序中访问您的模板实例及其属性。
  2. 无论如何都需要为您的模板助手提供一个“反应式”数据源,以便它在现场进行更改。
  3. 即使您在创建自己的响应式数据源时遇到了麻烦,您使用此功能的方法仍然会在页面上为 X 数量的 cmets 创建 X 数量的变量。要实现一个功能,内存中的变量似乎非常多。

我建议您将模板简化为:

<template name="comment_item">
  <li class="comment comment-displayed" id="{{_id}}">
   <div class="comment-body">
      <div class="comment-content">  <!-- changed this to a class -->
        <!-- some comment data here -->
      </div>
    </div>
  </li>
</template>

然后以编程方式将子 cmets 添加到事件处理程序的注释正文中。请记住 Meteor 文档中的以下内容:

您声明为&lt;template name="foo"&gt; ... &lt;/template&gt; 的模板 可以作为函数 Template.foo 访问,它返回一个字符串 调用时的 HTML。

哦,您将上下文作为 JSON 对象传递给模板函数。例如:

var context = {_id: comment_id, text: "Comment text!"};
Template.comment_item(context);

【讨论】:

  • 对于你的第二个答案,你能明确地给我们 js 来配合你的 html 吗?我是新手,我将使用您的第一个答案,因为我不知道如何为第二个答案编写 js。 (我认为它可能类似于template.find('.comment-body').append(Template.comment_item(context)),但需要进行一些调整......)
  • 也许Meteor.renderappendChilddocs.meteor.com/#meteor_render
【解决方案2】:

更新:

Meteor 现在允许您从帮助程序中访问模板实例,使用 Template.instance()。事实上,这是提高模板可重用性的好方法。

下面的示例来源来自this article,作者是 Percolate Studio 的 David Burles。

Template.hello.created = function () {
  // counter starts at 0
  this.state = new ReactiveDict();
  this.state.set('counter', 0);
}; 

Template.hello.helpers({
  counter: function () {
    return Template.instance().state.get('counter');
  }
});

Template.hello.events({
  'click button': function (event, template) {
    // increment the counter when button is clicked
    template.state.set('counter', template.state.get('counter') + 1);
  }
});

The article 很好地说明了您为什么需要这种方法。

在模板实例中存储信息的好处是您可以使模板越来越模块化,并减少对它们使用位置的依赖。

【讨论】:

    最近更新 更多