2

我正在尝试用 Ember 构建一个博客应用程序。我有不同类型帖子的模型——文章、书签、照片。我想显示用户创建的内容流,为此我需要所有这些模型的对象集合,这些模型按共同属性的降序排列,它们都具有“发布时间”。这该怎么做?

我尝试了类似的东西

App.StreamRoute = Ember.Route.extend({
    model: function() {
        stream = App.Post.find();
        stream.addObjects(App.Bookmark.find());
        stream.addObjects(App.Photo.find());
        return stream;
    }
}

资源名称在哪里stream

但它不起作用。我正在使用最新发布的 Ember 1.0.0 rc 2 和 handlebars 1.0.0 rc 3 以及 jQuery 1.9.1 和 ember-data。

可能我试图实现这一切的方式是错误的。问题是即使我能够使用多个模型的对象集合在模板中进行迭代,我仍然需要区分每个对象的类型以显示其属性,而不是“发布时间”的公共属性。

4

2 回答 2

4

您可以使用计算属性来组合各种数组,然后使用 Javascript 的内置排序功能对组合结果进行排序。

组合数组并对它们进行排序

计算属性来组合多个数组:

  stream: function() {
    var post = this.get('post'),
        bookmark = this.get('bookmark'),
        photo = this.get('photo');

    var stream = [];

    stream.pushObjects(post);
    stream.pushObjects(bookmark);
    stream.pushObjects(photo);
    return stream;
  }.property('post.@each', 'bookmark.@each', 'photo.@each'),

对包含所有项目的结果计算属性进行排序的示例:

  //https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/sort
  streamSorted: function() {
    var streamCopy = this.get('stream').slice(); // copy so the original doesn't change when sorting
    return streamCopy.sort(function(a,b){
      return a.get('publishtime') - b.get('publishtime');
    });
  }.property('stream.@each.publishtime')
});

根据属性或其类型呈现项目

我知道有两种方法可以做到这一点:

  1. 为每个对象添加一个布尔属性并使用把手{{#if}}来检查该属性并呈现正确的视图
  2. 扩展Ember.View并使用计算属性根据正在渲染的对象类型切换渲染哪个模板(基于使用 Ember.js 按模型类型/对象值选择视图模板

方法一

JS:

App.Post = Ember.Object.extend({
  isPost: true
});

App.Bookmark = Ember.Object.extend({
  isBookmark: true
});

App.Photo = Ember.Object.extend({
  isPhoto: true
});

模板:

<ul>
  {{#each item in controller.stream}}
      {{#if item.isPost}}
        <li>post: {{item.name}} {{item.publishtime}}</li>
      {{/if}}
      {{#if item.isBookmark}}
        <li>bookmark: {{item.name}} {{item.publishtime}}</li>
      {{/if}}
      {{#if item.isPhoto}}
        <li>photo: {{item.name}} {{item.publishtime}}</li>
      {{/if}}
  {{/each}}
   </ul>

方法二

JS:

App.StreamItemView = Ember.View.extend({
  tagName: "li",
  templateName: function() {
    var content = this.get('content');
    if (content instanceof App.Post) {
      return "StreamItemPost";
    } else if (content instanceof App.Bookmark) {
      return "StreamItemBookmark";
    } else if (content instanceof App.Photo) {
      return "StreamItemPhoto";
    }
  }.property(),

  _templateChanged: function() {
        this.rerender();
    }.observes('templateName')
})

模板:

<ul>
{{#each item in controller.streamSorted}}
    {{view App.StreamItemView contentBinding=item}}
{{/each}}
 </ul>

JSBin 例子——未排序的列表用方法一渲染,排序后的列表用方法二渲染

于 2013-04-08T01:31:47.277 回答
0

它比这有点复杂,但@twinturbo 的示例很好地展示了如何将单独的模型聚合到单个数组中。

显示聚合数组代理的代码:

App.AggregateArrayProxy = Ember.ArrayProxy.extend({
    init: function() {
        this.set('content', Ember.A());
        this.set('map', Ember.Map.create());
    },

    destroy: function() {
        this.get('map').forEach(function(array, proxy) {
            proxy.destroy();
        });

        this.super.apply(this, arguments);
    },

    add: function(array) {
        var aggregate = this;

        var proxy = Ember.ArrayProxy.create({
            content: array,
            contentArrayDidChange: function(array, idx, removedCount, addedCount) { 
                var addedObjects = array.slice(idx, idx + addedCount);

                addedObjects.forEach(function(item) {
                    aggregate.pushObject(item);
                });
            },
            contentArrayWillChange: function(array, idx, removedCount, addedCount) { 
                var removedObjects = array.slice(idx, idx + removedCount);

                removedObjects.forEach(function(item) {
                    aggregate.removeObject(item);
                });
            }
        });

        this.get('map').set(array, proxy);
    },

    remove: function(array) {
        var aggregate = this;

        array.forEach(function(item) {
            aggregate.removeObject(item);
        });

        this.get('map').remove(array);
    }
});
于 2013-04-07T20:35:13.060 回答