【问题标题】:Why didInsertElement hook trigger before elements rendered inside {{#each}} block?为什么在 {{#each}} 块内呈现元素之前会触发 InsertElement 挂钩?
【发布时间】:2014-07-30 06:17:49
【问题描述】:

我是 Ember 新手,我想向 {{#each}} 块中的元素添加一些查询 DOM 操作代码。于是我google了一下,从this guide找到了解决方案:

views/products/index.js

import Spinner from 'appkit/utils/someJqueryCode';

Ember.View.reopen({
  didInsertElement : function(){
    this._super();
    Ember.run.scheduleOnce('afterRender', this, this.afterRenderEvent);
  },
  afterRenderEvent : function(){
    // implement this hook in your own subclasses and run your jQuery logic there
  }
});

export default Ember.View.extend({
  afterRenderEvent: function() {
    Spinner();
  }
});

模板/产品/index.hbs

<div class='panel panel-default products'>
    <div class='panel-heading'>
        <h2 class='panel-title'>Our Prodcuts</h2>
    </div>
    <div class='panel-body'>
        <ul class='row'>
        {{#each}}
            <li class='col-md-4'>
    <div class='thumbnail'>
        <img {{bind-attr src=url alt=alt}} />
    </div>
    <div class='caption'>
        <h3 class='name-me'>{{name}}</h3>
        <p>{{description}}</p>
        <div class='row no-gutter'>
            <div class='col-xs-3'>
                <button class='btn btn-primary'>Buy</button>
            </div>
        </div>
    </div>
</li>
        {{/each}}
      </li>
  </div>
</div>

但我似乎在触发afterRenderEvent() 之后,{{#each}} 块中的所有元素还没有被渲染到 DOM,因此,jQuery 代码返回 undefined

正确的做法是什么?

【问题讨论】:

  • 你的模板是什么样的?
  • @JordyLangen 我已经更新了视图和模板的代码

标签: ember.js


【解决方案1】:

您的视图的didInsertElement 挂钩将在应用程序路由被渲染后立即触发,这发生在索引路由之前。您可能认为将它放在 index.js 文件中会起作用,但它只是扩展了默认的应用程序视图行为。

您需要在 index.hbs 文件中创建一个更集中的视图。一个只关心你的微调器 jQuery doohickey。那,以及每个/其他条件可以在这里很好地工作。例如:

{{#each}}
  {{#view App.SpinnerDoohickeyView}}
  <li class='col-md-4'>
    <div class='thumbnail'>
      <img {{bind-attr src=url alt=alt}} />
    </div>
    <div class='caption'>
      <h3 class='name-me'>{{name}}</h3>
      <p>{{description}}</p>
      <div class='row no-gutter'>
        <div class='col-xs-3'>
          <button class='btn btn-primary'>Buy</button>
        </div>
      </div>
    </div>
  </li>
  {{/view}}
{{else}}
  <li>Empty collection!</li>
{{/each}}

请注意,我已将每个列表项包装在其自己的视图中。如果你愿意,你可以包装整个ul...这只是一个例子。这个想法是你只有在有模型时才创建视图。

现在您可以定义视图,并且只需使用 didInsertElement 钩子来处理 jQuery:

App.SpinnerDoohickeyView = Ember.View.extend({
  didInsertElement: function () {
    this.$('li').css('background', 'blue');
  }
});

如果你有一个模型要渲染,jQuery 应该能够以这种方式安全地访问它。祝你好运!

这里有一些来自 Ember 人员的进一步阅读和一些代码,看起来就像我在这里展示的那样:http://emberjs.com/guides/views/handling-events/

【讨论】:

  • @mko 在代码中扩展视图时,您没有在应用程序中指定特定范围。因此,它在您的索引模型有机会渲染之前在应用程序路由上触发了它的钩子。因此,您的 jQuery 找不到 DOM 元素。
  • 1. 路由不负责渲染。意见是。在您的情况下,您扩展了基本应用程序视图。 2. 不,它指的是包装整个 ember 应用程序的基础视图。它不会出现在模板中,因为 ember 会自行创建它。 3. 我的意思是基本应用程序视图。 stackoverflow.com/questions/12712122/…
  • 阅读您的第一条评论后。我开始对我有意义了。所以我删除了这个问题。我会尝试更改代码,看看它是如何工作的。再次感谢您
  • @mko 当然,如果您需要任何其他帮助,请告诉我!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-19
相关资源
最近更新 更多