1

这是这个问题的一个小提琴(确保你的控制台打开):

基本上,我有一个车把块视图作为父级,然后循环遍历一组项目并为每个项目创建子块视图。后来,那些孩子以某种方式被修改了,我想检测并处理那个事件。

摘要代码:

{{#view App.outerView}}
    {{#each item in items}}
        <h6>Person:</h6>
        {{#view App.innerView}}
            <dl>
                <dt>First Name</dt><dd>{{item.first}}</dd>
                <dt>Last Name</dt><dd>{{item.last}}</dd>
            </dl>
        {{/view}}
    {{/each}}
{{/view}}

在稍后的某个时间点:

controller.get( 'items' ).pushObject( 'new item' );

在 jsFiddle 中,我试图保持最后一个子对象始终突出显示(活动 = true)。当最初插入 outerView 时,我们将高亮应用到最后一项,它按预期工作。稍后,当我们添加一个新项目时,我们的 highlight 方法会触发,但它看不到新项目。

2关于此的问题:

  • 主要问题:为什么最后一项(马特)没有突出显示?换句话说,为什么在添加了新项目后,childViews.length仍然报告旧值?有没有更好的方法来做到这一点?

  • 次要问题:为什么childViews添加新项目时观察者会着火两次?(总共 3 次:初始插入 1 次,添加 1 个新子项时 2 次)


编辑:我已经稍微调整了小提琴以更好地说明我的需求。注意outerView(HTML + innerViews)的混合内容。基本上,我的 outerView 需要接受任何内容作为子项,而不仅仅是视图/数据的数组/集合。

编辑2:进一步澄清:事后操作这些子视图是一个不同的故事,可以通过使用childViews(ember视图)的内容或使用jQuery来操作可能不是正式的ember视图对象的HTML元素来完成,或者任何其他方式。这里的真正目标只是在任何 outerView 内容发生变化时捕获事件(使用 childViews 的当前副本)。

编辑 3:这是Github 上的一个问题

4

2 回答 2

1

您的初始代码看起来有点复杂。这是实现相同结果的更好方法:

http://jsfiddle.net/XaN8T/1/

您应该将每个项目包装在一个控制器中,这很容易使用{{each}}助手完成:

<script data-template-name="application" type="text/x-handlebars">
    This is a list:
    <ul>
        {{each controller itemController="item" itemViewClass="App.ItemView"}}
    </ul>
</script>

并为您的项目创建一个单独的模板:

<script data-template-name="item" type="text/x-handlebars">
    <h6>Person:</h6>
    <div {{bindAttr class=":content active"}}>
        <dl>
            <dt>First Name</dt><dd>{{first}}</dd>
            <dt>Last Name</dt><dd>{{last}}</dd>
        </dl>
    </div>
</script>

然后你可以利用needsEmber 中的计算属性和active属性:

App.ItemController = Ember.ObjectController.extend({
    needs: ['application'], //This way each ItemController can access the ApplicationController's content (i.e. the list of all items)
    active: function() {
        return this.get('controllers.application.lastObject') === this.get('content');
    }.property('controllers.application.lastObject')
});

然后App.ItemView将其 css 类绑定到控制器的active属性:

App.ItemView = Ember.View.extend({
    tagName: 'li',
    templateName: 'item',
    classNameBindings: ['controller.active']
});

瞧!有用 :)

于 2013-03-27T19:32:32.480 回答
0

完成您在小提琴中完成的工作的更好方法是使用Ember.CollectionView

然后添加一个计算属性,该属性确定孩子是否是班级的itemViewClass最后active一个

active: function () {
  return this.get("elementId") === this.get("parentView.childViews.lastObject.elementId");
}.property('parentView.childViews.length'),

这是一个 工作小提琴

注意每当需要根据您的要求处理使用CollectionViewEmber.ContainerView的视图集合(这可以更好地控制子视图操作)时,但对于大多数情况Ember.CollectionView就足够了

于 2013-03-14T07:35:44.487 回答