如何在Ember中重新渲染视图的模板时收到通知?

时间:2013-12-09 10:15:53

标签: javascript view ember.js

当由于模型的更改而刷新视图的模板时,不会触发didInsertElement挂钩,因为Ember尝试尽可能多地重用视图。这给我带来了一些问题,因为我需要在重新渲染模板时选择列表的第一个元素。例如,当从服务器加载新数据或应用程序转换到不同的路径时,会发生这种情况。

奇怪的是,当应用程序转换到不同的路由时,会调用视图的init方法。问题是该模板尚未在那时呈现,也就是说,视图尚未填充控制器的新内容。

简而言之,如何在视图模板完成重新渲染后通知以便我可以操作视图的内容?

对于您的信息,观察控制器的模型不是一个选项,因为在回调被触发时视图尚未更新。

<script type="text/x-handlebars" id="list">
<div>
  <ul>
  {{#each model.items}}
    <li class="item">
      <p>{{title}}</p>
    </li>
  {{/each}}
  </ul>
</div>
</script>

更新在重新呈现each块时,需要通知视图。我想在this question中使用解决方案,但似乎只有each块被重新渲染而不是整个模板(这就是我想要的)。我可以在每个块中添加一个触发事件,但这非常昂贵,因为自定义事件将在each块的每个循环中触发。

2 个答案:

答案 0 :(得分:4)

也许这可行:

App.ListView = Ember.View.extend({
    templateName: 'list',
    contentChanged: function() {
        Ember.run.scheduleOnce('afterRender', this, 'selectFirstElement')
    }.observes('controller.content.[]'),
    selectFirstElement: function() {
        // for simplicity
        this.$('li:first').addClass('selected');
    }
});

如果在控制器内容中执行了某些更改,则使用observes('controller.content.[]')调用contentChanged函数。为了不在同一个runloop中多次调用该函数,我们使用Ember.run.scheduleOnce('afterRender', ...),因此只调用selectFirstElement一次,因为它是在afterRender队列中调度的,所以可以操纵dom。

现场演示http://jsfiddle.net/marciojunior/4b2V3/

答案 1 :(得分:0)

App.MagicView = Ember.View.extend({
  doMagic: function() {
    // magic goes here
  }.on('didInsertElement');
});

更新:我现在看到了。这是我的大脑转储:http://emberjs.jsbin.com/URidoBi/3/edit。不是最干净的方式,但应该让你解决问题。