Backbone.js의 get 및 set 함수 에 대한 간단한 질문이 있습니다.
1) 아래 코드를 사용하여 obj1.myAttribute1을 직접 ‘가져올’또는 ‘설정’할 수 있습니까?
다른 질문:
2) 모델에서 기본 객체를 제외하고 백본의 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;
하지만 그게 좋은 습관인가요?
답변
하지만 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/
답변
이를 위해 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
답변
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 을 참조하십시오 .
답변
이 접근 방식을 사용합니다.
다음과 같은 백본 모델이있는 경우 :
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}}
“변경”이벤트가 발생했습니다.
답변
아직 아무도 생각하지 못한 하나의 솔루션이 있으며 사용할 것이 많습니다. 원하지 않는 타사 라이브러리를 사용하지 않는 한 실제로 중첩 된 속성을 직접 설정할 수 없습니다. 그러나 할 수있는 일은 원본 사전의 복제본을 만들고 중첩 된 속성을 설정 한 다음 전체 사전을 설정하는 것입니다. 케이크 조각.
//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
답변
@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이하는 일은 이러한 작업을 허용하는 것입니다 (이는 JSON 데이터를 통해 myModel이 설정 될 때 발생합니다).
var myModel = new MyModel();
myModel.set({ obj1: { myAttribute1: 'abc', myAttribute2: 'xyz' } });
myModel.set('obj1', { myAttribute1: 123, myAttribute2: 456 });
초기화시 자동으로 모델 목록을 생성하는 것은 쉽지만이 솔루션은 저에게 충분했습니다.
답변
Domenic이 제안한 솔루션에는 몇 가지 단점이 있습니다. ‘변경’이벤트를 듣고 싶다고 가정 해 보겠습니다. 이 경우 ‘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);
},