console.lealog();

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

Backboneで作ったSPAをMarionette化してみた

こないだ作ったのをMarionette使ってみよう!というわで、Marionette化してみました。

参考:leader22/simple-pokedex

かかった時間

なんやかんや調べたりしたのと、あわせていろいろリファクタリングしてたので、だいたい半日くらいかかった。
でも一回やってだいたいの流れは掴んだので、次はその半分くらいでいけそう。
まあモデルもコレクションもその他諸々、ビュー周り以外は全部そのままやしね。

次は最初からMarionetteでってなったら、Backbone版を作ったときの2/3くらいでいけそう。
効率は上がるけど、まあこの程度の規模ならあんま変わらんですね・・。

ハマったとこ

モデルもコレクションも使わないビュー

ってあると思うんですけど。
でもデータはなんかしらあって、それを表示したい。
そんな場合に、どうやってデータをテンプレに渡すか。

こういうHTMLで、

<div id="my-region"></div>
<script id="my-view" type="x-my-tmpl">
  myVar: <%= myVar %>
</script>

こういうjs書けば良さそう。

var App = new Marionette.Application();

// ...

var View = Marionette.ItemView.extend({
  template: '#my-view',
  // serializeDataをオーバーライドして、データをcompileに渡す
  serializeData: function() {
    var data = { myVar: 'hoge' };
    return data;
  }

  // もしくは、templateをオーバーライドして固定のテンプレを返しちゃう
  /*
  template: function () {
    var $tmpl = $('#my-view').html();
    var data = { myVar: 'hoge' };
    return _.template($tmpl, data);
  }
  */
});

// ...

App.addRegions({
  myRegion: '#my-region'
});
App.myRegion.show(new View());
もしくは

ItemViewじゃなくて、Viewを使うってやり方もいけました。

// ...
var View = Marionette.View.extend({
  template: $('#my-view').html(),
  render: function() {
    var tmpl = _.template(this.template);
    var data = { myVar: 'hoge' };
    this.$el.html(this.template, data);
    return this;
  }
});
// ...

しかしもはや!

Note: The Marionette.View type is not intended to be used directly. It exists as a base view for other view types to be extended from, and to provide a common location for behaviors that are shared across all views.

まあでも公式がこう申されておるので、ItemView使って、serializeDataをオーバーライドするのが良いっぽいね。
あとはMarionette.Renderer.renderをオーバーライドしてたらしてたで・・とか、やり方は色々編み出せそう。

JST使いたい

これは一応公式にも記載がありました。

参考:Using jst templates with marionette · marionettejs/backbone.marionette Wiki

こんなコードで、Backbone.Marionette.Renderer.render を上書きすれば良いとのこと。

// Backbone.Marionette.Renderer.renderをオーバーライド
Backbone.Marionette.Renderer.render = function(template, data){
  if (!JST[template]) throw "Template '" + template + "' not found!";
  return JST[template](data);
}

あとはビューのtemplateで、なんてテンプレ名かを文字列で渡すだけでOK。
※先述のモデルもコレクションも使わないテンプレでJST使いたい場合は、selializeDataを上書きするパターンしか使えません。

とはいえどっかでJST読みこめば、もうグローバルに触れるので、なんとでもなるわなーって気もする。

思ったこと

いわゆるBackbone使って何か作る!ってなって、まず何から・・?ってなる感が薄くなったのはいいなと思いました。
あとはリージョンが変われば古いリージョンのイベントはがしてくれるとか、そのへんはMarionetteさまを信じて祈りを捧げることで心理的負担はだいぶ下がる気がする。
もはやSPA作るの、別に難しくないですね。(作るだけで良いなら

やっぱキモはリージョンとビューの重みづけですかねー。

正直、アプリケーション単位でしかリージョンもないし、ビューが入れ子でおれがあいつであいつがおれでみたいなカオティックゾーンでは元からないので、真価は発揮できてない感はあります。

気になったトコとしては、こういうライブラリのお作法に従って、どこまで行儀よくコードを書くべきなのか否か問題。
1つのDOMつかんで、都度都度なんかするのすらもビューとしてやるべきなのか、ただの便利関数にしちゃって良いのかとか、結構悩みました。
このへん、どう着地するのが一番しあわせになれるんでしょうねー。

あと、Require.jsとうまく付き合うためにどうすればええの論ももやもやあるのですが、それはまたの機会に・・。