web-dev-qa-db-ja.com

Backbone.jsビューでidとclassNameを動的に設定する

Backbone.jsを学習して使用しています。

アイテムモデルと対応するアイテムビューがあります。各モデルインスタンスにはitem_classおよびitem_id属性があり、対応するビューの 'id'および 'class'属性として反映したいです。これを達成する正しい方法は何ですか?

例:

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

var item1 = new ItemModel({item_class: "Nice", item_id: "id1"});
var item2 = new ItemModel({item_class: "sad", item_id: "id2"});

var ItemView = Backbone.View.extend({       
});

ビュー「el」が次のように変換されるように、ビューをどのように実装する必要がありますか?

<div id="id1" class="Nice"></div>
<div id="id2" class="sad"> </div>

私が見たほとんどの例では、ビューの エル 意味のないラッパー要素として機能し、その内部で「セマンティック」コードを手動で記述する必要があります。

var ItemView = Backbone.View.extend({
   tagName:  "div",   // I know it's the default...

   render: function() {
     $(this.el).html("<div id="id1" class="Nice"> Some stuff </div>");
   }       
});

したがって、レンダリングされると、

<div> <!-- el wrapper -->
    <div id="id1" class="Nice"> Some stuff </div>
</div>

しかし、これは無駄のようです-なぜ外部divがあるのですか?欲しい エル 内部divに直接変換します!

84
Nadav

要約:モデルデータを使用してビュー属性を動的に設定する

http://jsfiddle.net/5wd0ma8b/

// View class with `attributes` method
var View = Backbone.View.extend( {
  attributes : function () {
    // Return model data
    return {
      class : this.model.get( 'item_class' ),
      id : this.model.get( 'item_id' )
    };
  }
  // attributes
} );

// Pass model to view constructor
var item = new View( {
  model : new Backbone.Model( {
    item_class : "Nice",
    item_id : "id1"
  } )
} );
  • この例では、BackboneがDOM要素を生成できるようにしていることを前提としています。

  • attributesメソッドは、ビューコンストラクターに渡されるプロパティが設定された後に呼び出され(この場合はmodel)、Backboneがelを作成する前に、モデルデータで属性を動的に設定できます。

  • 他のいくつかの答えとは対照的に、ビュークラスに属性値をハードコーディングせず、モデルデータから動的に設定します。 render()がattr valsを設定するまで待機しません。 render()へのすべての呼び出しでattr valsを繰り返し設定しません。 DOM要素にattr valsを不必要に手動で設定することはありません。

  • Backbone.View.extendまたはビューコンストラクター(new Backbone.Viewなど)を呼び出すときにクラスを設定する場合は、DOMプロパティ名classNameを使用する必要がありますが、attributes hash /メソッド(この例のように)で設定する場合は、属性名、class

  • バックボーン0.9.9以降:

    ビューを宣言する場合、eltagNameid、およびclassNameは、実行時に値を決定する必要がある場合、関数として定義できるようになりました。

    図に示すようにattributesメソッドを使用する代わりにそれが役立つ状況がある場合にこれを言及します。

既存の要素を使用する

既存の要素を使用している場合(たとえば、elをビューコンストラクターに渡す)...

var item = new View( { el : some_el } );

...その場合、attributesは要素に適用されません。目的の属性が要素にまだ設定されていない場合、またはビュークラスと別の場所でそのデータを複製したくない場合は、initializeattributesに適用するビューコンストラクターにelメソッドを追加できます。このようなもの(jQuery.attrを使用):

View.prototype.initialize = function ( options ) {
  this.$el.attr( _.result( this, 'attributes' ) );
};

elの使用、レンダリング、ラッパーの回避

私が見たほとんどの例では、ビューのelは意味のないラッパー要素として機能し、その内部では「セマンティック」コードを手動で記述する必要があります。

view.elが「無意味なラッパー要素」である必要がある理由はありません。実際、それはしばしばDOM構造を壊します。たとえば、ビュークラスが<li>要素を表す場合、<li>としてレンダリングする必要があります。これを<div>としてレンダリングすると、コンテンツモデルが破損します。ビューの要素を正しく設定し(tagNameclassNameidなどのプロパティを使用)、その後、そのcontentをレンダリングすることに集中する必要があります。

BackboneビューオブジェクトがDOMと対話する方法のオプションは、広く公開されています。 2つの基本的な初期シナリオがあります。

  • 既存のDOM要素をBackboneビューに添付できます。

  • Backboneがドキュメントから切断された新しい要素を作成できるようにし、それを何らかの方法でドキュメントに挿入できます。

要素のコンテンツを生成するにはさまざまな方法があります(例のようにリテラル文字列を設定します。Mustache、Handlebarsなどのテンプレートライブラリを使用します)。ビューのelプロパティの使用方法は、実行内容によって異なります。

既存の要素

レンダリングの例では、ビューのインスタンス化は表示していませんが、ビューに割り当てる既存の要素があることを示唆しています。その場合で、要素がすでにドキュメントにある場合、次のようなことをしたいかもしれません(elの内容を更新しますが、el自体は変更しないでください):

render : function () {
  this.$el.html( "Some stuff" );
}

http://jsfiddle.net/vQMa2/1/

生成された要素

既存の要素がなく、Backboneが要素を生成できるようにするとします。あなたはかもしれませんこのようなことをしたいです(しかし、あなたのビューがそれ自体の外にあることを知る責任を負わないように物事を設計する方が良いでしょう):

render : function () {
  this.$el.html( "Some stuff" );
  $( "#some-container" ).append( this.el );
}

http://jsfiddle.net/vQMa2/

テンプレート

私の場合、テンプレートを使用しています、例:

<div class="player" id="{{id}}">
<input name="name" value="{{name}}" />
<input name="score" value="{{score}}" />
</div>
<!-- .player -->

テンプレートは完全なビューを表します。言い換えれば、テンプレートの周りにラッパーはありません-div.playerは私のビューのルートまたは最も外側の要素になります。

プレーヤークラスは次のようになります(render()の非常に単純化された例):

Backbone.View.extend( {
  tagName : 'div',
  className : 'player',

  attributes : function () {
    return {
      id : "player-" + this.model.cid
    };
  },
  // attributes

  render : function {
    var rendered_template = $( ... );

    // Note that since the top level element in my template (and therefore
    // in `rendered_template`) represents the same element as `this.el`, I'm
    // extracting the content of `rendered_template`'s top level element and
    // replacing the content of `this.el` with that.
    this.$el.empty().append( rendered_template.children() );
  }      
} );
132
JMM

あなたの意見では、このようなことをしてください

var ItemView = Backbone.View.extend({
   tagName:  "div",   // I know it's the default...

   render: function() {
     $(this.el).attr('id', 'id1').addClass('Nice').html('Some Stuff'); 
   }       
});
94
Dan Brooke

ルート要素にプロパティclassNameおよびidを設定できます。 http://documentcloud.github.com/backbone/#View-extend

var ItemView = Backbone.View.extend({
   tagName:  "div",   // I know it's the default...
   className : 'Nice',
   id : 'id1',
   render: function() {
     $(this.el).html("Some stuff");
   }       
});

[〜#〜] edit [〜#〜]コンストラクターのパラメーターに基づいてidを設定する例が含まれています

ビューが前述のように構築されている場合:

var item1 = new ItemModel({item_class: "Nice", item_id: "id1"});
var item2 = new ItemModel({item_class: "sad", item_id: "id2"});

次に、この方法で値を設定できます。

// ...
className: function(){
    return this.options.item_class;
},
id: function(){
    return this.options.item_id;
}
// ...
27
Jørgen

古い質問ですが、参考のために追加しました。これは、新しいバックボーンバージョンでは簡単に思えます。 Backbone 1.1では、idプロパティとclassNameプロパティは、アンダースコア_.resultensureElementまたはclassNameの場合に意味する関数idfrom source を参照)で評価されます関数であり、呼び出されます。それ以外の場合、その値が使用されます。

そのため、コンストラクターで直接classNameを指定したり、classNameで使用される別のパラメーターなどを指定したりできます。多数のオプション

これはうまくいくはずです

var item1 = new ItemModel({item_class: "Nice", item_id: "id1"});
var item2 = new ItemModel({item_class: "sad", item_id: "id2"});

var ItemView = Backbone.View.extend({       
  id: function() { return this.model.get('item_id'); },
  className: function() { return this.model.get('item_class'); }
});
6
Marcus

他の例は、モデルから実際にデータを取得する方法を示していません。モデルのデータからIDとクラスを動的に追加するには:

var ItemView = Backbone.View.extend({
   tagName:  "div",

   render: function() {
     this.id = this.model.get('item_id');
     this.class = this.model.get('item_class');
     $(this.el).attr('id',this.id).addClass(this.class).html('Some Stuff'); 
   }       
});
4
diskodave

TagNameを削除して、elを宣言する必要があります。

「tagName」は、バックボーンで要素を作成することを意味します。要素がすでにDOMに存在する場合、次のようにelを指定できます。

el: $('#emotions'),

以降:

render: function() { 
     $(this.el).append(this.model.toJSON());
}
2
jskulski

Initializeメソッドで値を割り当ててみてください。これにより、idとクラスがdiv属性に直接動的に割り当てられます。

var ItemView = Backbone.View.extend( {
    tagName : "div",   
    id      : '',
    class   : '',

    initialize : function( options ) {
        if ( ! _.isUndefined( options ) ) {
            this.id = options.item_id;
            this.class= options.item_class;
        }
    },

    render : function() {
        $( this.el ).html( this.template( "stuff goes here" ) ); 
    }
} );
1
Hemanth

モデルを介してビューの要素のクラスを動的に変更し、モデルの変更時に更新する最小限の方法を次に示します。

var VMenuTabItem = Backbone.View.extend({
    tagName: 'li',
    events: {
        'click': 'onClick'
    },
    initialize: function(options) {

        // auto render on change of the class. 
        // Useful if parent view changes this model (e.g. via a collection)
        this.listenTo(this.model, 'change:active', this.render);

    },
    render: function() {

        // toggle a class only if the attribute is set.
        this.$el.toggleClass('active', Boolean(this.model.get('active')));
        this.$el.toggleClass('empty', Boolean(this.model.get('empty')));

        return this;
    },
    onClicked: function(e) {
        if (!this.model.get('empty')) {

            // optional: notify our parents of the click
            this.model.trigger('tab:click', this.model);

            // then update the model, which triggers a render.
            this.model.set({ active: true });
        }
    }
});
0
Emile Bergeron