2016/06/20

Recent entries from same category

  1. Web Component を簡単に作れる JavaScript ライブラリ「X-Tag」
  2. twitter.bat
  3. jQueryプラグインとして動作するGithub Badge作ってみた。
  4. XSLとjQuery/HTMLだけで作る、amazon最速検索
  5. Google+でとりあえず全部+1押しちゃうブックマークレット書いた。

SPA でアプリケーションを作る際、angular1 の時はどうも「書かされている」感がして好きになれませんでした。x-tag を使って自前でカスタムエレメントを作っても良いのですが、それでも書かされている感がしますし、若干大げになりがちです。そんな中、angular 寄りで、かつ x-tag よりも薄い JavaScript ライブラリを tokuhirom がガシガシと作ってくれました。

GitHub - tokuhirom/sj.js

Tiny javascript view for custom elements based on incremental-dom. This library supports angular1 like templating.

https://github.com/tokuhirom/sj.js

x-tag の様に js 一つで動きます。そしてだいたい angular っぽく動きます。動作はコチラで確認して下さい。

<div sj-app="">
 
<p>Input something in the input box:</p>
<p>Name : <input type="text" sj-model="this.name" placeholder="Enter name here"></p>
<h1>Hello <span sj-bind="this.name"></span></h1>

</div>

まずこのソースの短さを見て下さい。コードは何も書いてません。機能的には angular のそれと同じですがモデル(sj-model)やバインド(sj-bind)を指定する際に this が必要という事が異なります。angular や riot.js の場合は独自に式をパースし実行ていますが、そこをスコープに依存した JavaScript 式で書ける様にしてあります(元々は式パーサも実装していましたがコードベースが肥大してきたのでこの方式に転換)。またテンプレートは angular の様に {{ name }} という書き方にする事は出来ません。以下の様にノードを用意する必要があります。

<h1>Hello <span sj-bind="this.name"></span></h1>

当初はこの {{ name }} というテンプレートを実装していましたが、サーバサイドテンプレートとの相性が良くない(間違って使った場合に意図しない eval 発火が起きる)のを理由に、バインド方式に変更されました。

イベントハンドラも一通り揃っています。

<script>
function CounterApp() {
  this.counter = 0;
  this.count = function() {
    this.counter++;
    this.update();
  }
}
</script>

<div sj-app="CounterApp">
<button sj-click="this.count()">Click Me!</button>
<p sj-bind="this.counter"></p>
</div>

this は sj-app 属性を持ったのノードを指します。試しに動かしてみたい方はコチラで確認して下さい。

また sj-app にはコールバック関数名を指定できるので初期化を行う事もできます。自前でデータを更新したい場合は update() を呼び出します。もちろん repeat も動きます。その他のサンプルはココから参照して下さい。

また sj ではカスタムタグを生成する事も可能です。

customElements.define('sj-books'class extends sj.Element {
  template() {
    return `
      <h3>Books</h3>
      <input type="text" sj-model="this.filter" placeholder="検索するキーワードを入力して下さい" class="books-filter" />
      <input type="button" sj-disabled="!!!this.filter" sj-click="this.clear()" value="クリア" />
      <div class="books-container">
        <div sj-repeat="x in this.books">
          <div class="item" sj-if="this.matched(x,this.filter)" sj-click="this.clicked($index)">{{x.name}}</div>
        </div>
      </div>
    `;
  }

  initialize() {
    this.books = [];
    this.clear = () => {
      this.filter = '';
      this.update();
    };
    this.clicked = (index) => {
      const URI = 'http://www.amazon.co.jp/gp/search/';
      location.href = URI + `?field-keywords=${encodeURIComponent(this.books[index].name)}`;
    };
    this.matched = (x,filter) => !!!filter || x.name.toLowerCase().indexOf(filter.toLowerCase()) != -1;
  }

  get books() {
    return this.b;
  }

  set books(b) {
    this.b = b;
    this.update();
  }
});

この例では書庫検索画面を sj-books という Web Component に仕上げています。動作を確認したい人はコチラで確認できます。コードを見て貰えると sj の薄さ、そして「書かされている感」がそれほどしない事が分かって頂けると思います。

angular 程色んな事が出来る訳ではありませんが、アプリケーションを作るには十分機能がそろったライブラリになっています。ライセンスは MIT です。

Posted at by