web-dev-qa-db-ja.com

ネストされたビューとモデルを構造化するbackbone.js

Backbone.jsの使用:

2つの属性と2つのネストされたモデル、ModelBとModelCを含む最上位のModelAがあります。 ModelBとModelCにはそれぞれ次の2つの属性があります。

ModelA
    attributeA1
    attributeA2
    ModelB
        attributeB1
        attributeB2
    ModelC
        attributeC1
        attributeC2

ModelAにはViewAがあり、ModelBにはViewBがあります。 ViewAのレンダリング関数は新しいdivをボディに配置しますが、ViewBのレンダリングはh1を作成します。 ViewAの初期化は、ViewBのレンダリングを呼び出して、そのh1を新しいdivに挿入します。この分離の背後にある理論的根拠は、h1が変更され、ViewAから独立した再レンダリングを必要とする可能性があることです。

ViewA
    initialise: 
        //call ViewA's own render function
        this.render() 

        //call ViewB's render function that further modifies the $("#new") div created earlier.
        $("#new").append(ViewB.render().el)

    //ViewA's own render function
    render: //place <div id="new"></div> onto 'body'

ViewB
    render: //create a <h1></h1>
    funcB1: //can this access it's parent ModelA's attributes and other objects?

Q1:ViewBには関数funcB1があります。この関数は親モデルの属性にアクセスできますか? attributeA1、またはattributeC1(兄弟/いとこ)などの属性はありますか?

Q2:Q1へのさらなる拡張として、funcB1はViewAに関連付けられたDOM要素にアクセスできますか? (この例では、#new div?)

Q3:一般に、上記のようにビューとモデルの間の関連付けを定義して、すべてが適切に結びつくようにするにはどうすればよいですか?

この質問はやや抽象的ですが、ヘルプやガイドラインに感謝します。

71
fortuneRice

関連するモデルの属性に到達できるようにするには、モデルに関連するモデルに関する何らかの知識が必要です。 Backbone.jsは、リレーションまたはネストを暗黙的に処理しません。つまり、モデルがお互いの知識を持っていることを確認する必要があります。質問に答えるには、各子モデルに「親」属性があることを確認することが1つの方法です。この方法では、最初に親までネストをトラバースし、次に知っている兄弟までトラバースできます。

質問をより具体的にするため。 modelAを初期化するとき、おそらくmodelBとmodelCを作成します。これを行うときは、次のように親モデルへのリンクを設定することをお勧めします。

ModelA = Backbone.Model.extend({

    initialize: function(){
        this.modelB = new modelB();
        this.modelB.parent = this;
        this.modelC = new modelC();
        this.modelC.parent = this;
    }
}

この方法では、this.parentを呼び出すことにより、任意の子モデル関数で親モデルに到達できます。

ビューに関して、ネストされたバックボーンビューを実行する場合、ビューのtagNameオプションを使用すると、各ビューが1つのHTMLタグを表すようにする方が簡単です。私はあなたの意見を次のように書きます:

ViewA = Backbone.View.extend({

    tagName: "div",
    id: "new",

    initialize: function(){
       this.viewB = new ViewB();
       this.viewB.parentView = this;
       $(this.el).append(this.viewB.el);
    }
});

ViewB = Backbone.View.extend({

    tagName: "h1",

    render: function(){
        $(this.el).html("Header text"); // or use this.options.headerText or equivalent
    },

    funcB1: function(){
        this.model.parent.doSomethingOnParent();
        this.model.parent.modelC.doSomethingOnSibling();
        $(this.parentView.el).shakeViolently();
    }

});

次に、アプリケーションの初期化コード(コントローラーなど)で、ViewAを開始し、その要素をbody要素内に配置します。

73
Jens Alm

上記の解決策は正しい軌道に乗っていますが、いくつかの問題があります。

initialize: function(){
  this.viewB = new ViewB();
  this.viewB.parentView = this;
  $(this.el).append(this.viewB.el);    
}

主に、モデルのtoJSON()は古いデータを返すようになりました。 backbone.jsプラグイン でこの問題を解決するソリューションを投稿しました。あなたはそれを使用することを歓迎します。

3
geddesign

「Can I」という質問に対する一般的な答えは、常に「はい、コードを書いても構わないと思っている限り」です。バックボーンの背後にあるポイントは、モデルとビューを強力に分離することです。 B1にA1への参照があり、A1にC1への参照がある場合、メソッドを作成し、B1がA1およびC1などを変更できるルールを設定できます。

ビューは、それぞれのモデルからCRUDイベントを受信するように設定する必要があります。ユーザーがB1viewを使用してB1modelを変更し、B1modelがA1modelを変更すると、A1modelはA1viewが受け取るイベントを生成し、A1viewの再レンダリングなどを行う必要があります。それは魔法のように起こるはずです。 (実際には、魔法を正しく実行するには時間がかかりますが、Backboneは非常に強力であることがわかりました。BackboneRelationalは、ここで説明しているようなことを支援します。)

3
Elf Sternberg

Backbone-Forms https://github.com/powmedia/backbone-forms などのいくつかの拡張機能を使用できます。ユースケースに従うには、次のようなスキーマを定義します。

var ModelB = Backbone.Model.extend({
    schema: {
        attributeB1: 'Text',
        attributeB2: 'Text'
    }
});

var ModelC = Backbone.Model.extend({
    schema: {
        attributeC: 'Text',
    }
});

var ModelA = Backbone.Model.extend({
    schema: {
        attributeA1: 'Text',
        attributeA2: 'Text',
        refToModelB: { type: 'NestedModel', model: ModelB, template: 'templateB' },
        refToModelC: { type: 'NestedModel', model: ModelC, template: 'templateC' }
    }
});

部分的なテンプレートについては、 https://github.com/powmedia/backbone-forms#customising-templates をご覧ください。

ここで重要な部分はtype: 'NestedModel'およびtemplate: 'templateXXX'

このプラグインにはいくつかの制限がありますが、 https://github.com/documentcloud/backbone/wiki/Extensions%2C-Plugins%2C-Resources で他のプラグインを見ることができます。

2
Artem Oboturov

Backboneのモデル間に1対1、1対多、および多対1の関係を提供するBackboneプラグインBackbone-relational.jsがあります。

このjsはあなたのニーズを満たすと思います。 Vist BackboneRelational その他のドキュメント。

0
Gagan