在components section at Ember's guides中有发布摘要组件的演示, 点击一个Post Summery标题会打开它下面的内容。
我想添加功能以同时关闭任何其他已打开的帖子摘要。
我的问题的目的是理解ember如何在不牺牲隔离的情况下在组件之间说话。
我想到的解决方案是:
有一些以某种方式处理它的包装器组件
触发像'post-summery:open'这样的事件并让其他组件靠近它(但是它可以使用相同的组件与app上的其他地方碰撞以进行不同的使用)
< / LI> 醇>这是文档中的原始演示: http://jsbin.com/uyibis/1/edit
这就是我用jQuery实现行为的方法: http://jsbin.com/eremon/2/edit
var $ contents = $('。content')。hide();
$(document).on('click','。title',function(){
$ contents.hide();
$(本)的.next( '内容')显示();});
答案 0 :(得分:5)
这个问题一直在Ember出现。我解决它的方法是跟踪控制器上哪个帖子“打开”,然后让每个项目的视图根据该数据负责自己的状态。这样,每次切换时,您都不必手动重置每个帖子的状态。
规范的真相来源是控制者。
App.IndexController = Ember.ArrayController.extend({
content: null,
selectedPost: null // null means no post selected
});
我们通过模板将这些信息连接到组件。
<script type="text/x-handlebars" data-template-name="index">
{{#each post in controller}}
{{post-summary post=post selectedPost=selectedPost}}
{{/each}}
</script>
<script type="text/x-handlebars" id="components/post-summary">
<h3 {{action "toggleBody"}}>{{post.title}}</h3>
{{#if isShowingBody}}
<p>{{{post.body}}}</p>
{{/if}}
</script>
现在,可以通过属性计算给定帖子的正文可见性。
App.PostSummaryComponent = Ember.Component.extend({
post: null,
selectedPost: null,
isShowingBody: function() {
return this.get('selectedPost') === this.get('post');
}.property('selectedPost', 'post'),
toggleBody: function() {
this.set('selectedPost',
this.get('isShowingBody') ? null : this.get('post'));
}
});
有人可能会说这不是一个理想的面向对象的解决方案,但它已经彻底改善了我的Ember应用程序的结构和可维护性。您可以通过让每个元素基于共同的事实来源来管理自己的状态来实现各种复杂的列表行为。
答案 1 :(得分:2)
使用Ember.Component
您无法控制childViews,因此我使用Ember.CollectionView
来管理项目。由于App.PostSummaryComponent
已经扩展Ember.Component
,因此我使用模板中的Ember.CollectionView
委托view containerViewClass
该行为。所以我们拥有两个世界中最好的一个。
由于containerViewClass
属性是一个类,我们需要一种方法来访问该实例 - 在创建视图时与childViews
进行交互。为此,您必须在模板中使用viewName='containerView'
。这告诉Ember,containerViewClass
的新实例将在名为containerView
的属性中设置。因此,我们可以在this.get("containerView")
中使用App.PostSummaryComponent
。
最后一项更改是将each
帮助程序从索引模板移动到组件模板。所以其他人对该组件的调用不需要重复它。