如何在 Ember 中(重新)渲染视图模板时收到通知?
Posted
技术标签:
【中文标题】如何在 Ember 中(重新)渲染视图模板时收到通知?【英文标题】:How to be notified when a view's template is (re)rendered in Ember? 【发布时间】:2013-12-09 10:15:52 【问题描述】:当视图的模板由于模型的变化而被刷新时,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
块的每个循环中触发。
【问题讨论】:
您能否显示您想知道何时重新渲染的视图/模板的代码? Ember 只是重新渲染执行更改的 html 部分,因此如果您的 #each 正在更改,则只有EachView
实例将收到重新渲染事件,而不是整个 @987654329 @。这是为 ember 提供的优化之一。
@MárcioRodriguesCorreaJúnior 我明白了,但是当EachView
被重新渲染时如何通知ListView
?
看看我的回答,也许能帮上忙
【参考方案1】:
也许这可行:
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/
【讨论】:
这太棒了。这绝对不是一个简单的解决方案,但它非常有效,尤其是在添加scheduleOnce
时。【参考方案2】:
App.MagicView = Ember.View.extend(
doMagic: function()
// magic goes here
.on('didInsertElement');
);
更新:我现在明白了。这是我的大脑转储:http://emberjs.jsbin.com/URidoBi/3/edit。不是最干净的方法,但应该可以解决问题。
【讨论】:
由于问题中概述的原因,这不起作用。重新呈现视图的模板时,不会调用didInsertElement
挂钩。如果可以,Ember 将重用视图,这意味着在重新渲染视图时不会调用 didInsertElement
挂钩。以上是关于如何在 Ember 中(重新)渲染视图模板时收到通知?的主要内容,如果未能解决你的问题,请参考以下文章