vaguely

和歌山に戻りました。ふらふらと色々なものに手を出す毎日。

Backbone.jsを使ってみる

前々回作成したタブの切替部分を、Backboneを使って置き換えてみました。

準備

必要なファイルを取得して、javascriptファイルと同じ、「public/js」以下に置きます。

※その他、「json2.js」も入れている方もいるようですが、とりあえず今回は使用していません。

ファイルの読み込み

layout.slimで上記ファイルを読み込みます。

layout.slim

doctype html
html
  head
    meta charset="utf-8"
    title TabTest
    link href="/css/stylesheet.css" rel="stylesheet"
  body onload==@updateTabs
    main#main
      == yield
    script src='/js/jquery-2.1.3.min.js'
    script src='/js/underscore-min.js'
    script src='/js/backbone-min.js'
    script src='/js/javascript.js'
  • この際気をつけることは、あるjavascriptが別のものに依存している場合、依存されている方を先(上)に記述する必要があることです。
    (順番が間違っていたため「Backbone is not defined」とエラーになりました...)
    • BackboneはUnderscoreに依存しているため「underscore-min.js」 -> 「backbone-min.js」の順で記述
    • javascript.jsからjQueryやBackboneを呼び出すので一番後(下)に記述

タブへのclass名、dataset追加

Backboneで置き換える部分のタブ(ラジオボタン)に、class名とdatasetを追加します(詳細は後述)。

viewTab.slim

section#tab_frame
  input#arrow_button_left type="button" onclick="moveTabLeft();"
    label.arrow_label for="arrow_button_left" <
  input#tab_0.tab_radio type="radio" name="tabs" data-tab-num='0'
    label#tab_label_0.tab_label for="tab_0"
  input#tab_1.tab_radio type="radio" name="tabs" data-tab-num='1'
    label#tab_label_1.tab_label for="tab_1" タブ2
  input#tab_2.tab_radio type="radio" name="tabs" data-tab-num='2'
    label#tab_label_2.tab_label for="tab_2" タブ3
  input#tab_3.tab_radio type="radio" name="tabs" data-tab-num='3'
    label#tab_label_3.tab_label for="tab_3" タブ4
  input#tab_4.tab_radio type="radio" name="tabs" data-tab-num='4'
    label#tab_label_4.tab_label for="tab_4" タブ5
  input#arrow_button_right type="button" onclick="moveTabRight();"
    label.arrow_label for="arrow_button_right" >
〜省略〜

dataset

HTML5では、タグに対してIDやClass以外に独自でデータを持たせることができます。
書き方は「data-」の後ろにハイフンつなぎで名前を指定し、持たせたいデータを記述します。

input#tab_0.tab_radio type="radio" name="tabs" data-tab-num='0'

javascript(jQuery)側で受け取るときは以下のようにします。

var intNewPageNum = jQuery(strTargetId).data('tabNum');

「data-*」の要素名は、そのまま指定するほか「data-」の部分を省き、後ろの部分をキャメルケース(ハイフンで繋がれた単語の頭を大文字にする)で指定することもできるようです。

BackboneのViewを使う

さて、ここからが本題。

細かいことはさておき、コードは以下のように変更しました。

Before

javascript.js

〜省略〜
this.movePage = function(intNewPageNum){
  // 次のページに遷移する. 一番右のTab番号をパラメータとして付与.
  location.href='?tab=' + intNewPageNum + '&lrt=' + intRightTabNum;
};
〜省略〜

After

javascript.js

(function () {
〜省略〜
  var TabView = Backbone.View.extend({
    el: '.tab_radio',
    events: {
      'change': 'movePage'
    },
    movePage: function (e) {
      var strTargetId = '#' + e.target.id;
      var intNewPageNum = jQuery(strTargetId).data('tabNum');
      location.href='?tab=' + intNewPageNum + '&lrt=' + intRightTabNum;
    }
  });

  var view = new TabView();
〜省略〜

関数を呼び出す部分をHTML側に書いていたこともあり、だいぶコードが増えた感がありますね…。

Viewを利用するには「Backbone.View」を継承したオブジェクトを作成する必要があります。
その中身は以下の通り。

  • el: ビューに関連付ける要素名(クラスorID)を指定します。
  • events: 関数を呼び出すトリガーとなるイベント(今回はonChange)と、呼び出すメソッド(movePage)を設定します。
  • movePage: 設定したイベントによって実行される関数です。

関数が実行された時に、対象の要素からIDを取得する

上記のコードではクラス名をビューに関連付けているため、同じクラス名を持つ要素であればどれでも同じメソッドが実行されることになります。

今回はそれぞれ別の値をパラメータとして渡したいため、関数が実行されたときに、イベントを発生させた要素からIDを取得し、その要素が持つdatasetを取得してみました。

var strTargetId = '#' + e.target.id;
var intNewPageNum = jQuery(strTargetId).data('tabNum');

関数の引数として渡されるeのtargetを使うことで、イベントを発生させた要素の情報が取得できるようです。

ただし、IDを取得すると「tab_0」のように「#」を省いた文字列が返るため、dataset取得のために「#」を追加しています。

気になるところなど

サンプルなどを見ると、イベント・メソッドを指定する部分「events:{}」で「'change #tab_0': 'movePage'」のようにIDやクラス、タグ名を指定しているのですが、実際にやってみるとイベントが実行されないというところ。

また、SinatraのようにHTMLのテンプレートも扱えるようなので、そちらも非同期で画面を切り替える場合などに利用できたら、と思います。

参考

Backbone.js

dataset