console.lealog();

@leader22のWeb系に関する勉強めもブログですのだ

いまさらBackbone.jsでSPAぽいものを作ったので

反省と学びをメモしておきます。

リポジトリは、

参考:leader22/simple-pokedex

ご参考まで。

2014/04/24現在、Backbone.Marionetteで作りなおしました。

作ったものの概要

簡単なポケモン図鑑です。
布団の中でWiFi対戦に潜ってて、「そもそもコイツ何タイプ・・?」とか、「コイツって耐久あるんやっけ?」とかなったとき、
対戦wikiGoogleで検索してる時間はないけどサクッと知りたい・・!っていう個人的ニーズのもと作られました。

  • あいうえおから検索
  • 図鑑No順の一覧から検索

すると、種族値と特性とタイプ相性がわかります。
それだけ。

実装的には、

  • Backbone.jsでできてる
  • Require.jsで依存管理
  • いわゆるSPA
  • JSTはプリコンパイル
  • 1ソースでバイリンガル対応
  • マスタデータはLocalStorageに貯めてる
  • フラットデザイン風

やってみたかった感満載の一品となっております。

所感つらつら

  • Backboneは確かに背骨
  • でも背骨だけでは何も成せない
  • underscoreとjQueryはほんとにすごい
  • Require.jsは個人的に賛否両論
  • 規模はどうあれ結局、設計がイノチ

Backbone.jsの勘所

自分の作りたいものと比較して、コレだ!っていうサンプルが見つからなかったのが辛かったです。
よって、出来上がったコードも正解ではないんやろなーって箇所がちらほらいます。

いちおう、今後のために書き留めておきたいBackboneのノウハウ的なのは以下です。

Backbone.Routerが起点になる

さて、どこからコード書いていこうかってなったときに、ここから書き始めると良いと思いました。
いわゆるエントリーポイントってやつですかね。

ただこのRouterを起点に据えてしまうと、このアプリ全体!って概念と競合する気がするので、しっかり決めなきゃな感じ。

あとは今回みたく、Routingの度にViewのインスタンス作るのか、最初に全部作っちゃって、表示の切替だけにするのか、とか。
今となっては、

  • Viewは最初に全部インスタンスつくる
  • RouterはViewの表示の切替メソッドだけ叩く
  • DOMの更新が必要なViewは、そこを勝手に更新する

みたいなのが良かったかなーと思ったりも。

Collection.fetchを保証してからViewを

なんだかしかCollection的なものをサーバーサイドとやりとりするのであれば、これは重要だと思われます。
Ajaxでデータ取ったりしてると、Viewの切り替え時にはまだレスポンスが返ってきてなくて白い画面が・・みたいのは回避したいので。
そもそもRouterでViewを切り替える部分で、Collectionのfetchなりをフックしてあげる必要がありそうです。

幸いな事に、 Backbone.Collection.fetch は jqXHR を返してくれるので、こういうことができました。

myCollectionFetch.done(function() {
  new MyView({
    el: '#my-view',
    collection: myCollection
  });
});

Collection.fetch を自作する場合は、$.Deferred()でも使って、同じ感じになるようにすれば良い感じです。

背骨の限界

あと一歩的な意味で、物足りなさを感じる箇所がちらほら。

onBeforeRouteみたいなイベントも欲しくなってくるし。
Viewの切り替えと同時に document.title を書き換えるとか、定型化するリンクのイベント管理とか、
逐一Viewに実装していくとなんだかなーみたいなやつらのやり場がなかったり。
あと1Route1Viewだったのでなんとかなってますが、コレは増えてきたら破綻するニオイがします。

まあこのあたりは、Backbone経験値を積めばなんとかなりそう(慣れそう)です。
Marionetteとかはそういうのを解決してくれるんやろうか。

最後までわからなかったこと

一応メモ。

Backbone.history.navigateどこまでやるか

上述のとおり、定型化するリンクをViewに実装するたびに、 events に記述を増やすのがどうもなーと思ってまして。
aタグのhrefに直接 #hoge って書いても動くので、もうそれでいいのでは・・と何度も心が折れそうになりました。
いい落とし所はどこなんでしょうか。

Collectionとうまくやる方法

これはなんか見落としてるだけな気もするんですけど・・。

Backbone.Collection は Underscore.jsのいくつかのメソッドが使えます!的なことが書いてますが、

myCollection.comparator = 'name';
myCollection.sort(); // OK

myFilteredCollection = myCollection.filter();

myFilteredCollection.comparator = 'id';
myFilteredCollection.sort(); // NG: myFilteredCollection は、もはやBackbone.CollectionではなくBackbone.Modelのつまった配列

これはそういう仕様なのでしょうか。

あと先日記事にしたコレ。

参考:Backbone.Collection.get()がよくわからない - console.lealog();

うーん、わからない。

濁点含む文字列のうまいsort

これはなんかそもそもですけど・・。

var arr = ['カイロス', 'ガブリアス', 'カメックス'];
arr.sort(); // ["カイロス", "カメックス", "ガブリアス"] ってなるけど元のままでいてほしい

これ、どうしたらいいんかなー。
unicodeとかに分解して云々すればいいんかな・・。

Handlebarsのプリコンパイルがコケる

いろいろ調べたのですが、結局Underscoreのテンプレに乗り換えることで解決としました。

grunt-contrib-handlebarsが悪いとか、ランタイムのバージョンあげればなおるとか、
なんかいろいろ調べれば出てくるものの、結局どれもこれも効果がなく!
たぶんもうあのヒゲは使わないと思います・・・。

おわりに

ページ構成としてはたった4ページ。
機能も全然ないはずですが、それでも結構たいへんでした。
年明けからはじめたプロジェクトなので、製作期間はだいたい2ヶ月くらい。
(もっと余裕のある仕事に就いてればもっと早かったでしょうね・・・。)