gpt4 book ai didi

javascript - 排序 Backbone 集合

转载 作者:塔克拉玛干 更新时间:2023-11-02 22:36:06 26 4
gpt4 key购买 nike

所需的功能

我正在使用 Backbone.Collection 查看可排序列表中的数据。我已经了解了单击某些 dom 元素会在我的 Collection 上设置属性以确定我想要对哪个字段进行排序以及应该按哪个方向进行排序的部分。然后应该在集合上触发排序,之后 View 将更新。

最终我希望能够对数字字段和字符串进行排序。一些字符串应按字母顺序排序,其他字符串应按自定义预定义顺序排序。

我目前的做法

我找到了以下关于反向排序字符串的帖子: Sorting strings in reverse order with backbone.js

我尝试将其与比较器函数和以下自定义属性相结合:

  1. “状态”字段中可能值的自定义排序顺序
  2. 应该使用哪个字段进行排序
  3. 排序的方向

到目前为止我得到的 Collection 和 Model 类:

收藏

var ApplicationCollection = Backbone.Collection.extend({
model: ApplicationModel,
url: 'rest/applications',

// sorting
statusOrder: ['new', 'to_pay', 'payed', 'ready'],
sortField: 'submission_timestamp',
sortOrder: 'asc',
sortBy: function() {
console.log('ApplicationCollection.sortBy', this, arguments);
console.log('this.comparator', this.comparator);
var models = _.sortBy(this.models, this.comparator);
if (this.sortOrder != 'asc') {
models.reverse();
}
return models;
},
comparator: function(application) {
console.log('ApplicationCollection.comparator', this, arguments);
switch(this.sortField) {
case 'status':
return _.indexOf(this.statusOrder, application.get(this.sortField));
break;
case 'submission_timestamp':
default:
return application.get(this.sortField)
break;
}
}
});

模型

var ApplicationModel = Backbone.Model.extend({
defaults: {
'drupal_id': 0,
'language': '',
'last_name': '',
'first_name': '',
'address': '',
'zip_code': '',
'city': '',
'country': '',
'telephone': '',
'cell_phone': '',
'email': '',
'date_of_birth': '',
'email': '',
'date_of_birth': '',
'pilot_training_institute': '',
'date_of_exam': '',
'flight_hours_total': '',
'date_of_last_flight': '',
'date_of_mcc_certificate': '',
'date_of_ir_renewel': '',
'package': '',
'submission_timestamp': '',
'status': 'new'
},
urlRoot: 'rest/applications'
});

当前(不需要的)结果

我有一个集合实例存储在“pendingApplications”中,如下所示:

var pendingApplications = new ApplicationCollection();
pendingApplications.fetch();

这会从服务器加载应用程序,并且一切都按计划进行。我可以渲染一个包含应用程序列表的 View ,所有属性都在模型上,等等。

为了对集合进行排序,我执行以下操作:

pendingApplications.sortOrder = 'asc';
pendingApplications.sortField = 'current_timestamp'; // format: YYYY-mm-dd HH:mm:ss
pendingApplications.sort();

这会触发集合的排序功能。控制台告诉我“ApplicationCollection.sortBy”方法在“pendingApplications”实例的范围内执行,这是预期的。

但是,“ApplicationCollection.comparator”方法在全局范围内执行,我不确定为什么。比较器方法的参数也不包含“pendingApplications”实例。

我希望我的比较器方法在“pendingApplications”实例的范围内执行,或者至少我希望能够以某种方式访问​​“pendingApplications”实例的属性。

范围问题?错误的做法?欢迎任何建议...

有谁知道我该如何解决这个问题?还是我以错误的方式解决这个问题,是否有另一种解决方案可以在 Backbone.Collection 上任意定义自定义排序?

解决方案

我最终实现了排序功能作为 Backbone.Collection 的装饰器。这样做的原因是因为我还有一个装饰器用于过滤集合中的项目。通过使用排序装饰器,我可以对过滤后的项目子集应用排序,这可能会更快。

/**
* returns a new Backbone.Collection which represents a sorted version of the
* data contained within the original Backbone.Collection.
*
* @param {Backbone.Collection} original
*/
SortedCollection: function(original, criteria) {
var sorted = new original.constructor(),

// sensible defaults
defaultSortCriteria = {
custom: {},
field: 'id',
direction: 'asc'
};

// configuration
sorted.sortCriteria = _.extend(defaultSortCriteria, criteria);

// do the stuff
sorted.comparator = function(a, b) {
// @formatter:off
var criteria = this.sortCriteria,
custom,
field = criteria.field,
direction = criteria.direction,
valA,
valB;
// @formatter:on

// custom sort
if (_.has(criteria.custom, field)) {
custom = criteria.custom[field];

// custom param is a comparator itself.
if (_.isFunction(custom)) {
return custom(a, b);
}
// custom param is an example of a sorted array.
else if (_.isArray(custom)) {
valA = _.indexOf(custom, a.get(field));
valB = _.indexOf(custom, b.get(field));
}
else {
throw new Error('Invalid custom sorting criterium.');
}
}
// nothing custom here, use the field value directly.
else {
valA = a.get(field);
valB = b.get(field);
}

// compare that shizzle!
if (valA > valB) {
return (direction == 'desc') ? -1 : 1;
}
if (valA < valB) {
return (direction == 'desc') ? 1 : -1;
}
else {
if (a.get('id') > b.get('id')) {
return (direction == 'desc') ? -1 : 1;
}
else if (a.get('id') < b.get('id')) {
return (direction == 'desc') ? 1 : -1;
}
else {
return 0;
}
}
};

// update collection if original changes
original.on("add", function(model) {
sorted.add(model);
});
original.on("reset", function() {
sorted.reset(original.models);
});
original.on("remove", function(model) {
sorted.remove(model);
});

return sorted;
}

装饰器的使用:

original = new ApplicationsCollection();
sortable = SortedCollection(original);
sortable.sortCriteria = {
sortField: 'submission_timestamp',
sortDirection: 'desc'
}
sortable.sort();

上面的代码片段做了以下事情:

  • 实例化一个新的 ApplicationsCollection;
  • 实例化一个扩展原始集合的可排序集合并监听原始集合上的相关事件。
  • 告诉可排序集合按“submission_timestamp”属性降序排序。
  • 对可排序集合进行排序。

当新模型添加到原始集合或从原始集合中删除时,或者当原始集合被重置时,新的可排序集合也会自动保持排序。

最佳答案

默认情况下,comparator() 函数在集合范围内调用,至少在最新版本的 Backbone 中是这样。

我怀疑您可能通过定义 sortBy() 函数破坏了它。该函数已经由 Backbone 定义,并且在某些情况下由 Backbone 的 sort() 函数在内部使用。尝试删除该功能,看看它是否按预期工作。

看来您只是在使用 sortBy() 来反转排序顺序。这可以在 comparator() 函数中通过在适当的时候将返回值乘以 -1 来完成。

关于javascript - 排序 Backbone 集合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11801660/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com