107

Backbone.jsのget関数とset関数について簡単な質問があります。

1)以下のコードで、obj1.myAttribute1を直接「取得」または「設定」するにはどうすればよいですか?

別の質問:

2)モデルでは、デフォルトオブジェクトとは別に、Backboneのgetメソッドとsetメソッドを介してアクセスできるように、モデルの他の属性をどこで宣言できますか/宣言する必要がありますか?

var MyModel = Backbone.Model.extend({
    defaults: {
        obj1 : {
            "myAttribute1" : false,
            "myAttribute2" : true,
        }
    }
})

var MyView = Backbone.View.extend({
    myFunc: function(){
        console.log(this.model.get("obj1"));
        //returns the obj1 object
        //but how do I get obj1.myAttribute1 directly so that it returns false?
    }
});

私は私ができることを知っています:

this.model.get("obj1").myAttribute1;

しかし、それは良い習慣ですか?

4

9 に答える 9

145

大丈夫ですが、セットに対して同じタイプのことをthis.model.get("obj1").myAttribute1したくなるかもしれないので、少し問題があります。

this.model.get("obj1").myAttribute1 = true;

ただし、これを行うとmyAttribute1、変更イベントや検証などのバックボーンモデルのメリットを享受できなくなります。

より良い解決策は、モデルにPOJSO(「プレーンな古いJavaScriptオブジェクト」)をネストせず、代わりにカスタムモデルクラスをネストすることです。したがって、次のようになります。

var Obj = Backbone.Model.extend({
    defaults: {
        myAttribute1: false,
        myAttribute2: true
    }
});

var MyModel = Backbone.Model.extend({
    initialize: function () {
        this.set("obj1", new Obj());
    }
});

次に、アクセスコードは次のようになります

var x = this.model.get("obj1").get("myAttribute1");

しかし、もっと重要なのは、設定コードは

this.model.get("obj1").set({ myAttribute1: true });

適切な変更イベントなどを発生させます。ここでの実例:http://jsfiddle.net/g3U7j/

于 2011-06-14T23:44:12.337 に答える
75

このためにbackbone-deep-modelを作成しました。Backbone.Modelの代わりにBackbone.DeepModelを拡張するだけで、パスを使用してネストされたモデル属性を取得/設定できます。変更イベントも維持します。

model.bind('change:user.name.first', function(){...});
model.set({'user.name.first': 'Eric'});
model.get('user.name.first'); //Eric
于 2011-11-05T13:57:43.683 に答える
16

Domenicのソリューションは機能しますが、新しいMyModelはそれぞれObjの同じインスタンスを指します。これを回避するには、MyModelは次のようになります。

var MyModel = Backbone.Model.extend({
  initialize: function() {
     myDefaults = {
       obj1: new Obj()
     } 
     this.set(myDefaults);
  }
});

完全な説明については、 c3rinの回答@https://stackoverflow.com/a/6364480/1072653を参照してください。

于 2012-02-19T23:16:05.293 に答える
5

私はこのアプローチを使用します。

このようなバックボーンモデルがある場合:

var nestedAttrModel = new Backbone.Model({
    a: {b: 1, c: 2}
});

属性「ab」は次のように設定できます。

var _a = _.omit(nestedAttrModel.get('a')); // from underscore.js
_a.b = 3;
nestedAttrModel.set('a', _a);

これで、モデルには次のような属性が含まれます。

{a: {b: 3, c: 2}}

「変更」イベントが発生しました。

于 2013-03-06T18:11:23.707 に答える
3

まだ誰も考えていない解決策が1つあり、それを使用することがたくさんあります。おそらく不要なサードパーティのライブラリを使用しない限り、ネストされた属性を直接設定することはできません。ただし、元のディクショナリのクローンを作成し、そこにネストされたプロパティを設定してから、ディクショナリ全体を設定することができます。ケーキ。

//How model.obj1 looks like
obj1: {
    myAttribute1: false,
    myAttribute2: true,
    anotherNestedDict: {
        myAttribute3: false
    }
}

//Make a clone of it
var cloneOfObject1 = JSON.parse(JSON.stringify(this.model.get('obj1')));

//Let's day we want to change myAttribute1 to false and myAttribute3 to true
cloneOfObject1.myAttribute2 = false;
cloneOfObject1.anotherNestedDict.myAttribute3 = true;

//And now we set the whole dictionary
this.model.set('obj1', cloneOfObject1);

//Job done, happy birthday
于 2016-08-22T13:57:54.083 に答える
2

@pagewilと@Bennoが@Domenicのソリューションで抱えていたのと同じ問題がありました。私の答えは、代わりに、問題を修正するBackbone.Modelの単純なサブクラスを作成することでした。

// Special model implementation that allows you to easily nest Backbone models as properties.
Backbone.NestedModel = Backbone.Model.extend({
    // Define Backbone models that are present in properties
    // Expected Format:
    // [{key: 'courses', model: Course}]
    models: [],

    set: function(key, value, options) {
        var attrs, attr, val;

        if (_.isObject(key) || key == null) {
            attrs = key;
            options = value;
        } else {
            attrs = {};
            attrs[key] = value;
        }

        _.each(this.models, function(item){
            if (_.isObject(attrs[item.key])) {
                attrs[item.key] = new item.model(attrs[item.key]);
            }
        },this);

        return Backbone.Model.prototype.set.call(this, attrs, options);
    }
});

var Obj = Backbone.Model.extend({
    defaults: {
        myAttribute1: false,
        myAttribute2: true
    }
});

var MyModel = Backbone.NestedModel.extend({
    defaults: {
        obj1: new Obj()
    },

    models: [{key: 'obj1', model: Obj}]
});

NestedModelが行うことは、これらが機能することを許可することです(これは、myModelがJSONデータを介して設定されたときに発生します)。

var myModel = new MyModel();
myModel.set({ obj1: { myAttribute1: 'abc', myAttribute2: 'xyz' } });
myModel.set('obj1', { myAttribute1: 123, myAttribute2: 456 });

初期化時にモデルリストを自動的に生成するのは簡単ですが、このソリューションは私にとっては十分でした。

于 2012-07-26T17:29:24.127 に答える
2

Domenicによって提案されたソリューションにはいくつかの欠点があります。'change'イベントを聴きたいとします。その場合、「initialize」メソッドは実行されず、属性のカスタム値はサーバーからのjsonオブジェクトに置き換えられます。私のプロジェクトでは、この問題に直面しました。モデルの「set」メソッドをオーバーライドするための私の解決策:

set: function(key, val, options) {
    if (typeof key === 'object') {
        var attrs = key;
        attrs.content = new module.BaseItem(attrs.content || {});
        attrs.children = new module.MenuItems(attrs.children || []);
    }

    return Backbone.Model.prototype.set.call(this, key, val, options);
}, 
于 2015-08-29T16:26:07.867 に答える
1

Domenicが述べたように、ネストされたオブジェクト属性の代わりにバックボーンモデルを使用することが理にかなっている場合もありますが、より単純なケースでは、モデルにセッター関数を作成できます。

var MyModel = Backbone.Model.extend({
    defaults: {
        obj1 : {
            "myAttribute1" : false,
            "myAttribute2" : true,
        }
    },
    setObj1Attribute: function(name, value) {
        var obj1 = this.get('obj1');
        obj1[name] = value;
        this.set('obj1', obj1);
    }
})
于 2015-06-02T22:40:13.140 に答える
0

バックエンドと対話する場合。これには、ネスト構造を持つオブジェクトが必要です。しかし、バックボーンを使用すると、線形構造での作業がより簡単になります。

backback.linearはあなたを助けることができます。

于 2015-07-21T01:08:22.407 に答える