【问题标题】:Re-sorting backbone collection from view从视图中重新排序骨干集合
【发布时间】:2013-05-04 15:00:46
【问题描述】:

我在利用点击事件处理我的收藏时遇到问题。为每个模型触发并执行排序功能,但既不会触发重置事件,也不会触发视图上的集合。

我在我的收藏中定义了多个排序标准,例如:

feNoRequire.Collections.CompetitionCollection = Backbone.Collection.extend({

    model: feNoRequire.Models.CompetitionModel,
    comparator: function (property) {
        return selectedStrategy.apply(model.get(property));
    },
    strategies: {
        name: function (competition) { return competition.get("name"); }, 
        nameReverse: function (competition) { console.log(competition); return -competition.get("name"); }, 
        date: function (competition) { console.log(competition.get("event")); },
    },
    changeSort: function (sortProperty) {
        this.comparator = this.strategies[sortProperty];
    },
    initialize: function () {
        this.changeSort("name");   
    }

});

在我的视图文件中:

initialize: function(options){
        this.evnt = options.evnt;

        this.collection.on('reset', this.render, this);     
        this.evnt.bind("orderByDate", this.changeSort, this);
    },

    changeSort: function(){
        this.collection.changeSort('nameReverse')
        this.collection.sort();
    },

    render: function() {
        console.log("going for rendering")
        var renderedContent = this.template({competitions: this.collection.toJSON()});

        $(this.el).html(renderedContent);
        return this;
    }

你知道如何解决这个问题吗?

编辑 在下面的答案之后,现在触发了渲染,但对象仅在初始化时进行排序。任何后续排序都以初始顺序返回集合 - this.changeSort("name");

我的模特:

feNoRequire.Models.CompetitionModel = Backbone.Model.extend({
    initialize: function(){
        this.attributes.events = new feNoRequire.Collections.EventCollection(this.attributes.events);
    }
});

【问题讨论】:

  • 'this.attributes.events = new feNoRequire.Collections.EventCollection(this.attributes.events);'
  • 对于每个模型,我都有一个我想成为模型的事件列表,以便我可以对它们进行排序。
  • 一个迟到的评论,当然,但在语义上,我会通过this.sort()View.changeSort 中对this.collection.sort() 的手动调用移动到集合的函数中;这样你就知道当你在集合上调用 changeSort() 时,它总是会重新排序。

标签: javascript backbone.js backbone-views


【解决方案1】:

来自fine manual

排序 collection.sort([options])

[...] 调用 sort 会触发集合上的 "sort" 事件。

所以调用sort 不会触发"reset" 事件(因为集合没有得到reset),它会触发"sort" 事件。所以你想:

this.collection.on('sort', this.render, this);

以及绑定到"reset"

演示:http://jsfiddle.net/ambiguous/34Ena/


我看到您正在调用 changeSort('nameReverse') 并且排序是这样做的:

nameReverse: function (competition) {
    return -competition.get("name");
}

这不会像你想的那样做,否定一个非数字字符串会给你NaN。这意味着您最终将尝试对NaNs 的列表进行排序,所有这些都是false

NaN  < NaN
NaN  > NaN
NaN == NaN

所以对NaNs 列表进行排序没有任何用处。如果要反转排序字符串,则必须使用两个参数比较器函数:

nameReverse: function(a, b) {
    a = a.get('name');
    b = b.get('name');
    return a < b ?  1
         : a > b ? -1
         :          0;
}

【讨论】:

  • 谢谢。这现在正在触发渲染,但数据未排序。还有其他想法吗?
  • @jribeiro:您的nameReverse 排序没有任何用处,否定字符串会给您NaN,而不是反转排序方向。看看我的更新。
  • 加 1 的好小提琴 :)
  • 工作就像一个魅力。谢谢
  • @muistooshort 使用this.listenTo(this.collection, 'sort', this.render) 来防止僵尸浏览会更好吗?
【解决方案2】:

您可以收听集合的sort 事件并执行渲染。尝试将事件绑定更改为:

this.collection.on('sort reset', this.render, this);     

【讨论】:

  • 谢谢。这现在正在触发渲染,但数据未排序。还有其他想法吗?
  • nameReverse比较器不正确,查看@mu的答案。
【解决方案3】:

非常好的代码设置。我真的很喜欢你通过策略对象调用排序函数的方式。

我认为这段代码的问题源于以下部分:

comparator: function (property) {
    return selectedStrategy.apply(model.get(property));
},

根据文档,比较器函数采用模型或迭代器(不是属性),也不确定 selectedStrategy 应该引用什么...这是您提供的代码之外存在的另一个函数吗?

Apply 还接受一个上下文对象作为“this”,以及一个参数数组。根据关于申请的 MDN 文档:

fun.apply(thisArg[, argsArray])

除非您的模型的属性是您想用作“this”的对象,否则我认为它无法正常工作。如果我也能看到模型定义,也许会更有意义。

编辑:在阅读了其他回复后,我意识到您正在观看重置事件而不是排序,所以我的回复可能只是对您的代码的误解,而不是毕竟问题:)

【讨论】:

  • 感谢您的回答。是的,排序可能存在一些问题,但第一次它工作得很好。随后的调用并没有真正对任何东西进行排序。有什么想法吗?
  • @muistooshort 是正确的关于:反向字符串排序。不过,我仍然看到您在比较器中所做的任何事情都有问题。在我看来,您似乎同时使用了比较器并应用错误。看看穆的小提琴。请注意,他的比较器函数将模型作为参数(而不是属性)。也看看这里 -> developer.mozilla.org/en-US/docs/JavaScript/Reference/… - 我从来没有见过任何以你使用它的方式使用 apply 的例子。也许如果您能提供更多背景信息,我可以进一步发表评论。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多