【问题标题】:How does Spacebars {{#each}} work?空格键 {{#each}} 如何工作?
【发布时间】:2015-09-06 23:48:17
【问题描述】:

我不明白空格键{{#each}} 模板标签会发生什么。
例如我有一个简单的事件代码:

'click #player': function(){
  var playerId = this._id;
  Session.set('selectedPlayer', playerId);
  Session.set('selectedPlayerName', this.name);
}

以及模板中这段对应的代码:

{{#each player}}
    <a href="#" id="player" class="{{selectedClass}}"></a>
{{/each}}

最后是这个助手:

'selectedClass': function(){
  return this._id
}

事件处理程序和辅助函数如何知道引用了哪些列表项?

【问题讨论】:

    标签: meteor spacebars


    【解决方案1】:

    在 Meteor 中,您拥有自己创建的所有模板。每次渲染模板时,都会给它一个数据上下文,这是一种奇特的说法,它创建了一个新的功能范围。该数据上下文存储在templateInstance().data 中。

    当您使用#each 时,您将为其中的任何内容创建一个新的数据上下文。您可以通过在返回上方的助手中添加console.log(this) 来检查这一点。

    onCreatedonDestroyedonRendered 中,this 指向templateInstace()。因此,每当您在回调中时,请使用 this.data 访问数据上下文。

    events 回调中,您有 2 个参数:event, template。这里,template 也指向templateInstance()

    在助手中,this 指向templateInstance().data,因此您只需调用this

    空格键不是魔法,它只是让 JS 看起来像 HTML 的一种方式。假设您的模板存储在views/templates.html 中,请查看.meteor/local/build/programs/web.browser/app/client/views/template.templates.html,这一切都有意义。

    【讨论】:

    • 非常感谢!我在 OS X 上安装了流星。看起来我有不同的文件夹结构。 ~/.meteor/ 中没有 /local 子文件夹,只有 /packages/ 和 /packages-metadata/。请建议我在哪里可以找到 .meteor/local/build/programs/web.browser/app/client/views/template.templates.html ?
    【解决方案2】:

    The {{#each}} template tag 的特殊之处在于它改变了它的内部上下文。
    事实上,每个模板都可以与一袋数据一起使用(例如帖子的标题和内容)。此数据包注册在模板的自己的上下文中,可以在帮助程序中使用this.someData 或通过在模板中简单地命名 ({{someData}}) 来引用。

    {{#if}} 等其他模板标签不会更改其中模板的上下文。您可以在博客文章模板中键入,该模板接收博客文章对象作为数据:

    <h3>{{title}}</h3>
    <p>{{content}}</p>
    
    {{#if userIsSecretAgent}}
      <blink>{{secretData}}</blink>
    {{/if}}
    

    (秘密是你必须以与文本相同的频率闪烁才能阅读它,这就是为什么这个标签被使用了这么长时间)


    {{#each}} 允许您将模板的内部上下文更改为迭代的当前对象,从而简单地访问您正在迭代的对象的内容。
    假设您要制作一个显示博客文章列表的博客文章模板:

    {{#each blogPosts}}
      <!-- Here, how do you gain access to each title, each content, ..? -->
      <!-- Well, the context has changed! -->
      <!-- Now we can directly access each datum of the iterable through the context -->
    
      <!-- The result simply becomes: -->
      <h3>{{title}}</h3>
      <p>{{content}}</p>
    
      {{#if userIsSecretAgent}}
        <blink>{{secretData}}</blink>
      {{/if}}
    {{/each}}
    

    {{#each}} 块内的上下文与父块不同,而是一篇博文,我们可以简单地通过名称来引用每个博文字段!

    但现在我们正在重复代码。重用我们以前的模板不是很好吗?

    {{#each blogPosts}}
      {{> blogPost}}
    {{/each}}
    

    blogPost 模板需要一个博客文章对象作为其上下文,我们使用{{#each}} 模板标签提供此上下文。

    助手的工作方式相同,只是您必须在其中输入this.titlethis.content。您还必须使用Template.instance() 在某些地方引用模板(而不是this)。

    更多魔法请见SpaceBars docs

    【讨论】:

      【解决方案3】:

      由此生成的 HTML 无效,因为多个元素具有相同的 id-attribute。事件处理程序很容易解释。 event-map 中的键分为event-type 和可选的event-targetevent-target 被传递给 jQuery,它容忍 ids 的无效使用。所以 jQuery 为所有 id 为 player 的元素添加了事件监听器。

      Matt K explained the rest pretty well.

      【讨论】:

      • 谢谢!这解释了一切。感谢您注意到这个错误。
      猜你喜欢
      • 2015-07-22
      • 2016-07-14
      • 2016-07-26
      • 2016-01-09
      • 1970-01-01
      • 1970-01-01
      • 2017-08-05
      • 2015-12-24
      • 2012-12-24
      相关资源
      最近更新 更多