4

在Ember 指南的组件部分中,有一个Post Summary Component的演示,单击一个 Post Summery 标题会在其下方打开其内容。

我想添加同时关闭任何其他打开的帖子摘要的功能。

我的问题的目的是了解 ember 如何在不牺牲隔离的情况下在组件之间说话。

我想到的解决方案是:

  1. 有一些包装组件以某种方式处理它

  2. 触发诸如“post-summery:open”之类的事件并让其他组件在其上关闭(但随后它可能会与应用程序上的其他地方发生冲突,使用相同的组件用于不同的用途)

这是文档中的原始演示:http: //jsbin.com/uyibis/1/edit

这就是我使用 jQuery 实现行为的方式:http: //jsbin.com/eremon/2/edit

var $contents = $('.content').hide();

$(document).on('click', '.title', function () {

$contents.hide();
$(this).next('.content').show();

});

在此处输入图像描述

4

2 回答 2

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'));
    }    
});

这是 jsfiddle

有人可能会说这不是一个理想的面向对象的解决方案,但它极大地改善了我的 Ember 应用程序的结构和可维护性。您可以通过让每个元素基于共同的事实来源负责自己的状态来实现各种复杂的列表行为。

于 2013-08-03T20:11:27.763 回答
2

由于Ember.Component您没有对 childViews 的控制,所以我使用Ember.CollectionView, 来管理项目。因为App.PostSummaryComponent已经 extends Ember.Component,我委托给在模板中Ember.CollectionView使用的那个行为。view containerViewClass所以我们拥有两个世界中最好的。

由于该属性是一个类,因此我们需要一种方法来访问该实例 - 以便在创建视图时containerViewClass与之交互。childViews为此,您必须viewName='containerView'在模板中使用。这告诉 Ember,containerViewClass将在名为 的属性中设置 的新实例containerView。所以我们可以使用this.get("containerView")in App.PostSummaryComponent

最后的更改是将each帮助程序从索引模板移动到组件模板。所以其他对该组件的调用不需要重复。

http://jsbin.com/ebayip/2/edit

于 2013-08-03T19:27:03.520 回答