[javascript] Backbone.js의 중첩 모델, 접근 방법

서버에서 제공되는 다음 JSON이 있습니다. 이를 통해 중첩 모델이있는 모델을 만들고 싶습니다. 나는 이것을 달성하는 방법이 확실하지 않습니다.

//json
[{
    name : "example",
    layout : {
        x : 100,
        y : 100,
    }
}]

다음과 같은 구조를 가진 두 개의 중첩 된 백본 모델로 변환되기를 원합니다.

// structure
Image
    Layout
...

그래서 레이아웃 모델을 다음과 같이 정의합니다.

var Layout = Backbone.Model.extend({});

그러나 아래의 두 가지 (있는 경우) 기술 중 이미지 모델을 정의하는 데 사용해야하는 기술은 무엇입니까? 아래 A 또는 B?

var Image = Backbone.Model.extend({
    initialize: function() {
        this.set({ 'layout' : new Layout(this.get('layout')) })
    }
});

또는 B

var Image = Backbone.Model.extend({
    initialize: function() {
        this.layout = new Layout( this.get('layout') );
    }
});



답변

Backbone 응용 프로그램을 작성하는 동안 동일한 문제가 있습니다. 임베디드 / 중첩 모델을 처리해야합니다. 꽤 우아한 해결책이라고 생각했던 약간의 조정을했습니다.

예, 객체 주변의 속성을 변경하기 위해 구문 분석 방법을 수정할 수 있지만 실제로는 모두 유지 관리가 불가능한 코드 IMO이며 솔루션 이라기보다 해킹에 더 가깝습니다.

귀하의 예를 위해 제안하는 것은 다음과 같습니다.

먼저 레이아웃 모델을 이렇게 정의하십시오.

var layoutModel = Backbone.Model.extend({});

다음은 이미지 모델입니다.

var imageModel = Backbone.Model.extend({

    model: {
        layout: layoutModel,
    },

    parse: function(response){
        for(var key in this.model)
        {
            var embeddedClass = this.model[key];
            var embeddedData = response[key];
            response[key] = new embeddedClass(embeddedData, {parse:true});
        }
        return response;
    }
});

모델 자체를 변경하지 않고 단순히 parse 메서드에서 원하는 개체를 다시 전달합니다.

이렇게하면 서버에서 읽을 때 중첩 된 모델의 구조가 보장됩니다. 이제 저장 또는 설정이 실제로 처리되지 않는 것을 알 수 있습니다. 적절한 모델을 사용하여 중첩 된 모델을 명시 적으로 설정하는 것이 합리적이라고 생각하기 때문입니다.

이렇게 :

image.set({layout : new Layout({x: 100, y: 100})})

또한 다음을 호출하여 중첩 된 모델에서 실제로 parse 메서드를 호출하고 있음을 유의하십시오.

new embeddedClass(embeddedData, {parse:true});

model필드에 필요한만큼 중첩 된 모델을 정의 할 수 있습니다 .

물론 중첩 된 모델을 자체 테이블에 저장하려는 경우에도 마찬가지입니다. 이것으로는 충분하지 않습니다. 그러나 객체 전체를 읽고 저장하는 경우이 솔루션으로 충분합니다.


답변

이 코드는 구문 분석을 재정의하라는 Peter Lyon의 제안의 예로 게시하고 있습니다. 나는 같은 질문이 있었고 이것은 나를 위해 일했습니다 (Rails 백엔드 사용). 이 코드는 Coffeescript로 작성되었습니다. 익숙하지 않은 사람들을 위해 몇 가지 사항을 명시했습니다.

class AppName.Collections.PostsCollection extends Backbone.Collection
  model: AppName.Models.Post

  url: '/posts'

  ...

  # parse: redefined to allow for nested models
  parse: (response) ->  # function definition
     # convert each comment attribute into a CommentsCollection
    if _.isArray response
      _.each response, (obj) ->
        obj.comments = new AppName.Collections.CommentsCollection obj.comments
    else
      response.comments = new AppName.Collections.CommentsCollection response.comments

    return response

또는 JS

parse: function(response) {
  if (_.isArray(response)) {
    return _.each(response, function(obj) {
      return obj.comments = new AppName.Collections.CommentsCollection(obj.comments);
    });
  } else {
    response.comments = new AppName.Collections.CommentsCollection(response.comments);
  }
  return response;
};


답변

백본 연관Backbone.AssociatedModel 에서 사용 :

    var Layout = Backbone.AssociatedModel.extend({
        defaults : {
            x : 0,
            y : 0
        }
    });
    var Image = Backbone.AssociatedModel.extend({
        relations : [
            type: Backbone.One,
            key : 'layout',
            relatedModel : Layout
        ],
        defaults : {
            name : '',
            layout : null
        }
    });


답변

Backbone 자체에 권장되는 방법이 있는지 잘 모르겠습니다. 레이아웃 개체가 백엔드 데이터베이스에 고유 한 ID와 레코드를 가지고 있습니까? 그렇다면 당신은 당신이 가지고있는 것처럼 그것을 자신의 모델로 만들 수 있습니다. 그렇지 않은 경우 중첩 된 문서로 남겨 둘 수 있으며 saveparse메서드 에서 JSON과 올바르게 변환되었는지 확인하십시오 . 이와 같은 접근 방식을 취하면 A 예제가 set제대로 업데이트 되기 때문에 백본과 더 일치 한다고 생각 attributes하지만 Backbone이 기본적으로 중첩 모델로 무엇을하는지 확실하지 않습니다. 이를 처리하려면 사용자 지정 코드가 필요할 수 있습니다.


답변

단순하게 유지하려면 옵션 B를 선택하겠습니다.

또 다른 좋은 옵션은 Backbone-Relational 을 사용하는 것 입니다. 다음과 같이 정의하면됩니다.

var Image = Backbone.Model.extend({
    relations: [
        {
            type: Backbone.HasOne,
            key: 'layout',
            relatedModel: 'Layout'
        }
    ]
});


답변

중첩 된 모델과 속성에 Backbone DeepModel 플러그인을 사용합니다.

https://github.com/powmedia/backbone-deep-model

바인딩하여 이벤트를 n 레벨 깊이로 변경할 수 있습니다. 예를 들면 :
model.on('change:example.nestedmodel.attribute', this.myFunction);


답변

rycfung의 아름다운 대답 CoffeeScript 버전 :

class ImageModel extends Backbone.Model
  model: {
      layout: LayoutModel
  }

  parse: (response) =>
    for propName,propModel of @model
      response[propName] = new propModel( response[propName], {parse:true, parentModel:this} )

    return response

달콤하지 않나요? 😉