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


85

私は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>

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

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があるのですか?elを内部divに直接変換したい!

回答:


133

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

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()属性値を設定するまで待機しません。render();を呼び出すたびに属性値を繰り返し設定するわけではありません。DOM要素に不必要に手動で属性値を設定しません。

  • 呼び出し時にクラスBackbone.View.extendまたはビューコンストラクター(例new Backbone.View)をclassName設定する場合は、DOMプロパティ名を使用する必要がありますが、attributesハッシュ/メソッドを介して設定する場合は(この例のように)、属性名を使用する必要があることに注意してくださいclass

  • バックボーン0.9.9以降:

    ビューを宣言すると... eltagNameidclassNameあなたはそれらの値は、実行時に決定することにしたい場合は、今、関数として定義することができます。

    図のようなattributes方法を使用する代わりにそれが役立つ状況がある場合に備えて、これについて言及します。

既存の要素を使用する

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

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

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

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

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

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

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

バックボーンビューオブジェクトをDOMと相互作用させる方法のオプションは広く開かれています。2つの基本的な初期シナリオがあります。

  • 既存のDOM要素をバックボーンビューにアタッチできます。

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

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

既存の要素

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

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() );
  }      
} );

属性プロパティを関数で上書きし、オブジェクトを再び返す素晴らしい方法です!
ケル

2
@Kelええ、ビューがインスタンス化される場所で繰り返しコードを使用することなく、質問が求めるような動的な何かを達成し、属性にモデルデータを入力するのは良い方法です。あなたはおそらくこれを知っていますが、それが明らかでない場合に備えてattributes、関数または他のいくつかとして提供できる他の多くのバックボーンプロパティのように、の値としてハッシュを返す関数を使用できるのはバックボーンの機能です値のタイプ。そのような場合、バックボーンは値が関数であるかどうかをチェックして呼び出し、戻り値を使用します。
JMM 2012

95

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

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'); 
   }       
});

これはこの質問に対する正解であり、受け入れる必要があります
リーチ4thelasers 2012

13
この回答は、モデルデータに基づいてビュー属性を動的に設定することを示しているのではなく、属性値をハードコーディングする別の方法を示しているだけです。
JMM 2012

3
@ JMM-彼のサンプルコードもモデルデータを使用していません。この回答は、彼のサンプルコードに基づいて機能します。明らかに、モデルデータを値の代わりに使用できます。
クリント

5
@クリント、私はそれがOPにとって明白であることを期待しません。「彼のサンプルコードもモデルデータを使用していません。」-それは彼が方法を知らないので、それ故に彼が助けを求めた理由です。彼がモデルデータ使用してview.elの属性設定する方法を尋ねていることは明らかであり、それをどのように行うかがわかりません。答えはそれを行う方法さえ示していません、そしてなぜあなたはとにかくそれをするためにレンダリングするまで待つのですか、それともあなたがレンダリングするたびにそれをやり直すのですか?「この答えは機能します...」-どのように機能しますか?そのように作成されたすべてのビューは、同じ属性値を持ちます。それが示す唯一のことは、ラッパーを回避する方法です。
JMM 2012年

OPは2012年2月から廃止されました。:(ここで別の1がこの回答のためです。
アルモ

27

プロパティclassNameidルート要素を設定できます: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");
   }       
});

編集コンストラクタパラメータに基づいて設定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;
}
// ...

3
私はその後、すべてがあるため、この答えが正しい感じていないItemView必要がありますid: 'id1'。これは、に基づいて実行時間で計算する必要がありmodel.idます。
fguillen 2012

もちろん、IDは任意の方法で設定できます。関数、変数などを使用します。私のコードには、ルート要素に値を設定する方法を示す例が含まれています。
ヨルゲン2012

コンストラクターパラメーターに基づいて値を動的に設定する方法を明確にする例を追加しました。
ヨルゲン

これが正解です。バックボーン機能を正しく使用して問題を解決します。
Marc-Antoine Lemieux 2014年

6

古い質問だと思いますが、参考のために追加しました。これは、新しいバックボーンバージョンでは簡単なようです。Backbone 1.1では、idプロパティとclassNameプロパティは、またはが関数である場合はアンダースコアを使用して関数で評価されensureElementソースから参照)、それ以外の場合はその値が使用されます。_.resultclassNameid

したがって、コンストラクターで直接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'); }
});

あなたの例は有効ではありません、あなたが望むでしょうid: function() { return this.model.get('item_id'); })
Cobby

4

他の例は、モデルから実際にデータを取得する方法を示していません。モデルのデータから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'); 
   }       
});

それは「this.className」または「this.class」ですか?
Gabe Rainbow

2

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

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

el: $('#emotions'),

以降:

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

2

initializeメソッドで値を割り当ててみてください。これにより、idとclassが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" ) ); 
    }
} );

@Michel Pleasaeは、このドキュメント、backbonejs.org
#View

0

これは、モデルを介してビューの要素のクラスを動的に変更し、モデルの変更時に更新するための最小限の方法です。

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 });
        }
    }
});
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.