寻找一种更有效的方法来设置和更改顺序Backbone模型属性

时间:2014-05-02 04:15:55

标签: javascript backbone.js underscore.js

使用Backbone.js,我创建了一个由Products模型组成的Product集合。每个Product模型都包含orderIndex属性。该集合使用此orderIndex属性作为其比较器。

在我的应用操作期间,我需要更改集合中某个产品的orderIndex值。当我这样做时,我还需要为集合中的其他模型调整orderIndex,以便它们仍然按顺序排列。例如,如果我从四个模型开始:

A -> orderIndex = 0
B -> orderIndex = 1
C -> orderIndex = 2
D -> orderIndex = 3

然后我将B的orderIndex更改为2,然后我还希望C更改为1,以便在集合上调用sort()时B和C切换位置:

A -> orderIndex = 0
B -> orderIndex = 2
C -> orderIndex = 1
D -> orderIndex = 3

使用原始设置的另一个例子是,如果我将A的orderIndex更改为3,那么我还需要B更改为0,C更改为1,D更改为2,导致:

A -> orderIndex = 3
B -> orderIndex = 0
C -> orderIndex = 1
D -> orderIndex = 2

我已经编写了一个函数来处理这个问题,但我觉得我更倾向于使用更多内置的下划线或js函数来实现这一点。这是我现在使用的功能:

adjustModelOrderIndex: function(model, newIndex){
    var currentOrderIndex = model.get("orderIndex");
    var newOrderIndex = newIndex;

    model.set({orderIndex: newOrderIndex});

    _.each(_.without(this.models, model), function(model){
        if(currentOrderIndex > newOrderIndex){
            if(model.get("orderIndex") >= newOrderIndex && model.get("orderIndex") <= currentOrderIndex){
                model.set({orderIndex: model.get("orderIndex") + 1});
            }
        }
        else{
            if(model.get("orderIndex") <= newOrderIndex && model.get("orderIndex") >= currentOrderIndex){
                model.set({orderIndex: model.get("orderIndex") - 1});
            }
        }
    }, this);

}

此函数存在于我的集合中,参数表示正在更改的模型,以及其orderIndex属性将更改为的值。

有人可以推荐更好的方法来实现这个目标吗?

1 个答案:

答案 0 :(得分:0)

我经常在Array.prototype.splice找到普通的raw array of models,以便在这种情况下提供很大的帮助。然后,您可以使用数组的自然顺序更新orderIndex属性:

var OrderedCollection = Backbone.Collection.extend({
    comparator: 'orderIndex',

    adjustModelOrderIndex: function(model, newIndex) {
        var currentOrderIndex = model.get("orderIndex");            
        if (newIndex === currentOrderIndex) return;

        // remove the model from the array
        this.models.splice(currentOrderIndex, 1);

        // reinject it at its new position
        this.models.splice(newIndex, 0, model);

        // update orderIndex
        this.each(function(model, ix) {
            model.set('orderIndex', ix);
        });

        // order changed, let's trigger a sort event
        // or use this.sort() if you prefer
        this.trigger('sort', this);
    }
});

样本用法:

var c = new OrderedCollection([
    {id: 'D', orderIndex: 3},
    {id: 'C', orderIndex: 2},
    {id: 'B', orderIndex: 1},
    {id: 'A', orderIndex: 0}
]);
// ["A", "B", "C", "D"]
c.on('sort', function() {
    console.log(c.pluck('id'));
});

c.adjustModelOrderIndex(c.get('B'), 0); //  ["B", "A", "C", "D"]
c.adjustModelOrderIndex(c.get('B'), 1); //  ["A", "B", "C", "D"]
c.adjustModelOrderIndex(c.get('B'), 2); //  ["A", "C", "B", "D"]
c.adjustModelOrderIndex(c.get('A'), 3); //  ["C", "B", "D", "A"]

使用http://jsfiddle.net/F6XSC/1/

进行演示