ジンジャー研究室

長めのつぶやき。難しいことは書きません。

JavaScriptのテンプレートエンジンを作ってみた

Gyotoku.js

行徳という場所で作ったので、Gyotoku.jsです。

Backbone.jsとかそれに近いMVCを構築していて、やっぱりViewはテンプレート使って書きたいなーって思うわけですが、イベントハンドリングするのにidとか色々埋め込んでセレクタで取ってくるのが面倒なんです。こうなんか「そこクリックした時はあのメソッドだよ!」みたいな感じでテンプレートに書いてしまいたいのです。
で、以前Angular.jsというフレームワークがそんな感じのテンプレートエンジンを持っていて、まぁControllerとかRouterとか要らないからテンプレートだけ欲しいです…という気持ちを引きずっていたので試しに書いてみたのがこちら、Gyotoku.jsになります。

主な特徴

  • イベントが発生した時に呼ぶメソッドをテンプレートで指定できます。
  • jQueryに強く依存しています。
  • 全体でソースが60行もありません。
  • ループできません。

パフォーマンス等については何も考えていないので、速くはないと思います。多分。
ループできないのは自分がまだ必要になっていないからです。

特徴

テンプレートがこんな感じで書けます。

<div id="template">
  <form _on="submit submit;reset resetDone">
    <ul>
      <li><dt>First Name</dt><input _val="homuhomu.firstName" _on="keydown updateFirstName"/></li>
      <li><dt>Last Name</dt><input _val="homuhomu.lastName" _on="keyup updateLastName"/></li>
      <li><dt>Full Name</dt><dd _text="homuhomu.fullName"></dd></li>
    </ul>
    <input type="submit" _render="renderSubmit" value="Submit"/>
    <input type="button" _on="click reset" value="Homuhomu"/>
  </form>
</div>

_onが一番の特徴で、これがやりたかっただけ。
属性はinvalidだけど気にしない。コンパイル時に消してくれます。

以下のようにしてjs側から使用します。

var data = {
  homuhomu: {
    firstName: 'Homura',
    lastName: 'Akemi',
    fullName: function(){
      return this.firstName + ' ' + this.lastName;
    }
  },
  ...
};

var controller = {
  updateLastName: function(){
    data.homuhomu.lastName = $(this).val();
    template.render(data);
  },
  ...
};

var template = Gyotoku.compile($('#template'), controller);
template.render(data);

HTMLは先に書いても、書いてから埋め込んでも大丈夫です。

雑感

テンプレートエンジンなめるなよみたいな実装ですが、とりあえず動いているので良しとします。振る舞い駆動といえば格好が付きますかね。

原型は1時間弱で出来たのに、デモを作ったりGitHubに上げたりReadme書いたり記事を書いたりしているとどんどん時間が過ぎていきますね。
デモ製作中に、keydownイベントで一つ前の値を取っちゃうとか、オブジェクトからメソッドを取り上げたらthisが狂うとか、色んなトラブルに見舞われました。JavaScript一体なんなの。

以上であります。