0

セットアップ

私は Backbone を初めて使用し、大量のデータを表示するために Backgrid で使用しています。データは、成分の 2 つのリストを表します。1 つは既存の値で、もう 1 つは更新された値です。DB にはこのデータの主キーがないため、古い成分と新しい成分を名前で手動で照合し、一致したデータから DB 更新を生成できるようにすることが目標です。これを行うためにingredientsOld、(database)、ingredientsNew(update.xml)、およびingredients. ingredientsOldおよびingredientsNewコレクションは、基本Ingredientモデルの単なるコレクションです。ingredientsただし、コレクションはIngredientComp、整数のステータス、 'old' 、および 'new' を含むモデルのIngredientコレクションですIngredient

var Ingredient = Backbone.Model.extend({});
var Ingredients = Backbone.Collection.extend({ model: Ingredient });
var IngredientComp = Backbone.Model.extend({
    constructor: function(attributes, options) {
        Backbone.Model.apply( this, arguments );

        if (attributes.o instanceof Ingredient) {
            this.o = attributes.o;
            console.log("Adding existing ingredient: "+this.o.cid);
        } else {
            this.o = new Ingredient(attributes.o);
            console.log("Adding new ingredient: "+this.o.get("name"));
        }
        if (attributes.n instanceof Ingredient) {
            this.n = attributes.n;
        } else {
            this.n = new Ingredient(attributes.n);
        }
    }
});
var IngredientComps = Backbone.Collection.extend({ 
    model: IngredientComp,
    comparator: function(comp){
        return -comp.get("status");
    }
});

var ingredientsOld = new Ingredients();
var ingredientsNew = new Ingredients();
var ingredients = new IngredientComps();

データは PHP によって生成され、次のように JSON に出力されます。

ingredientsOld.add([
        {"name":"Milk, whole, 3.25%","guid":"3BDA78C1-69C1-4582-83F8-5A9D00E58B45","item_id":16554,"age":"old","cals":"37","fat_cals":"18","protein":"2","carbs":"3","fiber":"0","sugar":"3","fat":"2","sat_fat":"1","trans_fat":"0","chol":"6","sod":"24","weight":"2.00","quantity":"1 each","parents":{"CC09EB05-4827-416E-995A-EBD62F0D0B4A":"Baileys Irish Cream Shake"}}, ...
ingredients.add([
        {"status":3,"o":{"name":"Sliced Frozen Strawberries","guid":"A063D161-A876-4036-ADB0-C5C35BD9E5D5","item_id":16538,"age":"old","cals":"77","fat_cals":"0","protein":"1","carbs":"19","fiber":"1","sugar":"19","fat":"0","sat_fat":"0","trans_fat":"0","chol":"0","sod":"0","weight":"69.60","quantity":"1 each","parents":{"BC262BEE-CED5-4AB3-A207-D1A04E5BF5C7":"Lemonade"}},"n":{"name":"Frozen Strawberries","guid":"5090A352-74B4-42DB-8206-3FD7A7CF9D56","item_id":"","age":"new","cals":"77","fat_cals":"0","protein":"1","carbs":"19","fiber":"1","sugar":"19","fat":"0","sat_fat":"0","trans_fat":"0","chol":"0","sod":"0","weight":"","quantity":"69.60 Gram","parents":{"237D1B3D-7871-4C05-A788-38C0AAC04A71":"Malt, Strawberry"}}}, ...

IngredientComp モデル (カスタム バックグリッド セルのレンダリング関数) から値を表示する場合、最初に次のように出力する必要があります。

render: function() {
    col = this.column.get("name");
    var v1 = this.model.get("o")[col];
    var v2 = this.model.get("n")[col];
    this.$el.html( v1 + "\n<br />\n<b>" + v2 + "</b>" );
    return this;
}

問題

this.model.get("o").get(col);関数が機能するのは、あるコレクションから別のコレクションに IngredientComp モデルを移動した後でのみです。Ingredients をあるコレクションから別のコレクションに移動する関数は次のとおりです。

function matchItems(oldId, newId) {
    var oldItem = ingredientsOld.remove(oldId);
    var newItem = ingredientsNew.remove(newId);
    ingredients.add({'status': 1, 'o': oldItem, 'n': newItem});
}

レンダリング関数を更新して、値を取得する両方の方法を試しましたが、少し遅くなり、問題を処理する適切な方法ではありません。

render: function() {
    col = this.column.get("name");

    // Investigate why the Ingredient model's get() method isn't available initially
    var v1 = this.model.get("o")[col];
    // The above line returns 'undefined' if the Ingredient model has moved from one
    // collection to another, so we have to do this:
    if (typeof v1 === "undefined"){ v1 = this.model.get("o").get(col)};

    var v2 = this.model.get("n")[col];
    if (typeof v2 === "undefined"){ v2 = this.model.get("n").get(col)};

    this.$el.html( v1 + "\n<br />\n<b>" + v2 + "</b>" );
    return this;
}

この問題の原因を特定できる人はいますか? Backbone-relational.jsについて少し調査しましたが、私が達成しようとしていることはやり過ぎのようです。

4

1 に答える 1

1

コンストラクター関数はモデルの作成をオーバーライドして遅延させるため、最初initializeに の代わりに を使用することをお勧めします。constructor

考えられる主な問題は、この if ステートメントで model.get('o') が別のものを返すことです。そうthis.oすることで、モデルに属性を設定するのではなく、モデルオブジェクトに設定します。したがって、モデルが実際に作成されるときはmodel.get('o')、バックボーン モデルではなく通常のオブジェクトです。

    if (attributes.o instanceof Ingredient) {
        this.o = attributes.o;
        console.log("Adding existing ingredient: "+this.o.cid);
    } else {
        this.o = new Ingredient(attributes.o);
        console.log("Adding new ingredient: "+this.o.get("name"));
    }

if ステートメントを次のように変更すると、問題が解決するはずです。

    if (attributes.o instanceof Ingredient) {
        this.o = attributes.o;
        console.log("Adding existing ingredient: "+this.o.cid);
    } else {
        this.set('0', new Ingredient(attributes.o));
        console.log("Adding new ingredient: "+this.o.get("name"));
    }
于 2014-03-17T20:31:55.180 に答える