Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
branch: master
173 lines (115 sloc) 10.619 kb

Backbone.View

BackboneのViewは、コードというよりはほとんど慣習に近い存在です ー ViewはHTMLやCSSについて何も決定付けることはなく、任意のJavaScriptテンプレーティングライブラリと合わせて使用できます。一般的なアイディアとしては、ページを全体を再描画せず、モデルが変更されたときにそれぞれが独立して更新できる、Modelに支えられたロジカルなViewとしてインターフェースを整理します。JSONオブジェクトを掘り、DOMの中にある要素を参照し、手動でHTMLを更新する代わりに、Viewのrender関数をモデルの"change"イベントに結びつけることができます ー そうすると、UIの中のモデルデータを表示しているすべての箇所は、いつでも即座に最新になります。

extend Backbone.View.extend(properties, [classProperties])

Viewはまずカスタムビュークラスを作ることから始めます。render関数をオーバーライドし、宣言するイベントを指定し、tagNameclassName、Viewのルート要素のidもおそらく指定するとよいでしょう。

var DocumentRow = Backbone.View.extend({

  tagName: "li",

  className: "document-row",

  events: {
    "click .icon":          "open",
    "click .button.edit":   "openEditDialog",
    "click .button.delete": "destroy"
  },

  render: function() {
    ...
  }

});

constructor / initialize new View([options])

新しいビューを作成するときに与えたオプションは、後から参照するためthis.optionsとしてViewにアタッチされます。いくつかの特殊なオプション modelcollectionelidclassNametagName、そしてattributes があり、それらが渡された場合はViewのプロパティとして直接アタッチされます。 initialize 関数がViewに定義されている場合、それはViewが最初に作られたときに呼ばれます。DOMの中に 既に 存在する要素を参照して、Viewを作成したい場合は new View({el: existingElement}) のようにオプションとして渡します。

var doc = Documents.first();

new DocumentRow({
  model: doc,
  id: "document-row-" + doc.id
});

el view.el

すべてのViewは、それが既にページに挿入されているかそうでないかに関わらず、常に何らかのDOM要素を所持しています( el プロパティ)。こうすることで、UIの描画を効率良く行うため、できるだけ少ないリフローとリペイントで、Viewはいつでもレンダリングでき、一度にすべてをDOMへ挿入するようになっています。ViewにtagNameclassNameidそしてattributesプロパティが指定されていれば、それらからthis.elが作られます。そうでない場合は、 el は空のdivになります。

var ItemView = Backbone.View.extend({
  tagName: 'li'
});

var BodyView = Backbone.View.extend({
  el: 'body'
});

var item = new ItemView();
var body = new BodyView();

alert(item.el + ' ' + body.el);

$el view.$el

Viewを示す要素のjQuery(またはZepto)オブジェクトがキャッシュされています。都度、DOM要素をオブジェクトでラップする代わりとして、便利に参照できます。

view.$el.show();

listView.$el.append(itemView.el);

setElement view.setElement(element)

BackboneのViewを違うDOM要素に適用したい場合、 setElement を使用します。このメソッドは$elの参照をキャッシュして、Viewがもつイベントの委譲を古い要素から新しい要素に移動させます。

attributes view.attrributes

ViewのelのDOM要素としての属性(id、class、data-propertiesなど)にセットされる、属性のハッシュまたはそのようなハッシュを返す関数です。

$ (jQuery or Zepto) view.$(selector)

jQueryまたはZeptoがページに読み込まれている場合、それぞれのViewは自身の要素の中をスコープとしてクエリーを実行する $ 関数を持ちます。このスコープにあるjQuery関数を使う場合、特定の要素をリストから取ってくるためにモデルのIDをクエリーの一部分として使う必要はなく、HTMLのクラス属性により強く依存するようになります。これは、view.$el.find(selector)の実行と等価です。

ui.Chapter = Backbone.View.extend({
  serialize : function() {
    return {
      title: this.$(".title").text(),
      start: this.$(".start-page").text(),
      end:   this.$(".end-page").text()
    };
  }
});

render view.render()

デフォルトの実装の render は何もしません。ViewのテンプレートをModelのデータからレンダリングし、新しいHTMLでthis.elを更新するような、独自のコードで上書きします。よい慣習として、コールチェーンを有効にするため render の最後でreturn thisします。

var Bookmark = Backbone.View.extend({
  render: function() {
    $(this.el).html(this.template(this.model.toJSON()));
    return this;
  }
});

Backboneは、あなたが好むHTMLテンプレーティングの方法にとらわれることなく関知しません。あなたの render 関数は、HTML文字列を置換することも、document.createElementでDOMツリーを作成することも同様に行うことができます。しかし、我々は素晴らしいJavaScriptテンプレーティングライブラリを選ぶことをおすすめします。Mustache.jsHaml-js、そしてEco、これらはすべて良い代替手段と言えます。そのように言うのも、ページにはUnderscore.jsが既にあるため_.templateを利用することができ、XSS対策のサニタイズが済んだデータを挿入する場合は、素晴らしい選択になるからです。

テンプレーティングによる方略がどのようなものであっても結局、JavaScriptでHTML文字列を配置する必要がなければ、それは良いことです。DocumentCloudでは、core.jsのアセットパッケージの一部として、/app/viewsに格納されたJavaScriptテンプレートをパッケージするのにJammitを利用しています。

remove view.remove()

DOMからViewを削除するために便利な関数です。$(view.el).remove()を呼び出すのと等価です。

make view.make(tagName, [attributes], [content])

オプションの属性とHTMLコンテントを伴って、与えられた型( tagName )のDOM要素を作成するのに便利な関数です。内部的にview.elを初期化するのに使用しています。

var view = new Backbone.View;

var el = view.make("b", {"class": "bold"}, "Bold! ");

$("#make-demo").append(el);

delegateEvents delegateEvents([events])

Viewの中のDOMイベントに対して、コールバックの宣言を提供するのにjQueryのdelegateを使用しています。 events ハッシュが直接渡されていない場合、this.eventsがソースとして使われます。イベントは、{"event selector": "callback"}という形式で記述します。コールバックは、Viewにあるメソッド名、または関数本体が直接指定されるかもしれません。セレクタを省略すると、イベントはViewのルート要素( this.el )に結びつけられます。デフォルトで、delegateEventsはViewのコンストラクタの中で呼び出され、単純にeventsハッシュを使用している場合は、すべてのDOMイベントが常にすでに接続されていることになり、自身でこの関数を呼び出す必要はありません。

eventsプロパティは events ハッシュを返す関数として定義することもでき、プログラム的にイベントを定義するほかに、親のViewのイベントを継承することも簡単にしてくれます。

delegateEvents を使用することはrender中に、jQueryを使って手動で子要素にイベントを結びつけることよりも、多くのアドバンテージを提供します。すべてのアタッチされているコールバックは、コールバックが呼び出されたとき、Viewオブジェクトを参照し続けるために、jQueryに引き渡される前にViewに結びつけられています。異なったeventsハッシュを伴って delegateEvents がもう一度実行されるようなときには、すべてのコールバックを削除し、新しく委譲を行います ー 別のモードで異なった動作を必要とする時があるViewにとって有用です。

文書内の検索結果を表示するViewは、このような見た目になるかもしれません:

var DocumentView = Backbone.View.extend({

  events: {
    "dblclick"                : "open",
    "click .icon.doc"         : "select",
    "contextmenu .icon.doc"   : "showMenu",
    "click .show_notes"       : "toggleNotes",
    "click .title .lock"      : "editAccessLevel",
    "mouseover .title .date"  : "showTooltip"
  },

  render: function() {
    $(this.el).html(this.template(this.model.toJSON()));
    return this;
  },

  open: function() {
    window.open(this.model.get("viewer_url"));
  },

  select: function() {
    this.model.set({selected: true});
  },

  ...

});

undelegateEvents undelegateEvents()

Viewに委譲されたすべてのイベントを削除します。Viewを一時的にDOMから削除または無効化するときに有用です。

Jump to Line
Something went wrong with that request. Please try again.