Riot+Gulp+Browserifyで時計サンプルを動かす

[Riot](http://riotjs.com/ja/)はReactライクなマイクロMVPライブラリです。タスクランナーを噛ませたいので[こちらのサンプル](Adding compiled Riot tags to your Gulp + Browserify build)を動くようにしたり、いろいろいじってみた。

- [デモ](http://110chang.github.io/riot-test/dest/)

時計を表示する`clock`タグを表示します。インスタンスごとに長針・短針・秒針の表示を変えています。マウスホバーでポーズします。

via http://www.triplet.fi/blog/adding_compiled_riot_tags_to_your_gulp_browserify_build/

# Riotタグを書く

Riotの特徴はなんといってもHTML+CSS+JavaScriptの混ぜ書き。一見HTMLに見えますが、JavaScriptとしてトランスパイルされます。

```html:clock.tag
<clock>
  <svg>
    <line></line>
    <circle></circle>
    ...
  </svg>

  <style scoped>
    :scope {
      ...
    }
    svg {
      ...
    }
    ...
  </style>

  <script>
    // ↑このscriptタグは省略できる
    // ↓メソッド構文
    test() {
      ...
    }
    // function文も共存する
    function hogehoge() {
      ...
    }
  </script>
</clock>
```

シンタックスはとりあえず、スクリプト部分に`script`タグを入れてHTMLのシンタックスにしてみた。

## scoped スタイル

`scoped`スタイルはトランスパイルされるとそのタグの子セレクタとなります。

```css
clock svg {
  ...
}
```

Firefoxだけは`scoped`属性を実装しているようです。

## メソッド構文

奇妙に見えますがRiotタグの中では

```html
<clock>
  test() {
    ...
  }
</clock>
```

という書き方ができます。これはES6のクラス構文のような感じです。

```js
class Clock {
  test() {
    ...
  }
}
```

同じタグの中に`function`文による定義が混じっていると、一瞬あれっ、てなります。

トランスパイル後は

```js
this.test = function() {
  ...
}.bind(this)
```

となります。この時の`this`はRiotタグのインスタンスになります。


# メインで呼び出す

RiotとRiotタグを`require`して`mount`します。

```js:main.js
var riot = require('riot');

require('./tags/clock.tag');

riot.mount('clock');
```

# GulpでRiotをトランスパイル

Riotタグのトランスパイルは[riotify](https://github.com/jhthorsen/riotify)が用意されています。あとは[baberifyと同様](http://qiita.com/110chang/items/624121e1c69f24525279#jsx%E3%82%92gulp%E3%81%A7%E3%82%B3%E3%83%B3%E3%83%91%E3%82%A4%E3%83%AB%E3%81%99%E3%82%8B%E3%81%AE%E3%81%AB%E5%BF%85%E8%A6%81%E3%81%AA%E3%83%91%E3%83%83%E3%82%B1%E3%83%BC%E3%82%B8)ですね。

```js:gulpfile.js
var gulp = require('gulp');
var browserify = require('browserify');
var riotify = require('riotify');
var source = require('vinyl-source-stream');

...

gulp.task('concat', function () {
  return browserify({
    debug: true,
    entries: ['path/to/main']
  }).transform([riotify])
    .bundle()
    .pipe(source('main.bundle.js'))
    .pipe(gulp.dest('path/to/dest/'));
});
```

# HTMLに組み込む

定義したタグとトランスパイルしたバンドルをHTMLに追加します。

```html:index.html
<!DOCTYPE html>
<html>
  <head>
    <title>Riot Clock</title>
  </head>
  <body>
    <clock></clock>
    <script src="main.bundle.js"></script>
  </body>
</html>
```

# ループ＆子タグ

設定を配列で用意して子タグにオプションを渡す構造にしてみた。まず、親タグを書く。

```html:clocks.tag
<clocks>
  <clock 
    each={ clocks // means this.clocks }
    some-opts={ someOpts // means this.clocks[*].someOpts }
    another-opts={ anotherOpts // means this.clocks[*].anotherOpts }
    ...
  ></clock>
  <script>
    this.clocks = [{
      // this child has no options
　　 }, {
      // this child has options
      someOpts: true
    }, {
      // this child has another options
      anotherOpts: true
    },
    // ...
    }];
  </script>
</clocks>
```

他のデータバインドやテンプレート言語の経験から

```html
<!-- Didn't work -->
<clocks each={ clocks }>
  <clock some-opts={ someOpts }></clock>
</clocks>
```
こう書きたくなりますが、違うみたいです。一方で、設定オブジェクトのプロパティをそのまま受け継いでおり、楽チンです。

メインでは両方のタグをマウントすればよし。

```js:main.js
var riot = require('riot');

require('./tags/clocks.tag');
require('./tags/clock.tag');

riot.mount('*');
```

HTMLには親タグのみ記述

```html:index.html
<clocks></clocks>
<script src="main.bundle.js"></script>
```


# その他

## モジュール化

タグ内部で普通に`require`を使えるので、今までBrowserify等使っていれば、同じ感覚でコーディングできます。

```html:clock.tag
<clock>
  ...
  <script>
    var $ = require('jquery');
    ...
  </script>
</clock>
```

いろいろ外部化したほうが見やすいような気がします。Min-inの`init`メソッドは自動で実行されます。

```js:mixin/clock.js
var ClockMixin = {
  init: function() {
    ...
  },
  test: function() {
    ...
  }
}
module.exports = ClockMixin;
```

```html:clock.tag
<clock>
  ...
  <script>
    var ClockMixin = require('path/to/mixin');
    this.mixin(ClockMixin);
  </script>
</clock>
```

ファイルが別になってしまうと、コンポーネントっぽさが失われてしまうというのはありますね。こうとか？

```html:clock.tag
<clock>
  ...
  <script>
    ...
    this.mixin({
      init: function() {
        ...
      },
      test: function() {
        ...
      }
    });
  </script>
</clock>
```

Mix-inはRiot的には、このように書くようです。これはまたシンタックスががが…

```html:clock.tag
var ClockMixin = {
  init: function() {
    ...
  },
  test: function() {
    ...
  }
}
<clock>
  ...
  <script>
    ...
    this.mixin(ClockMixin);
  </script>
</clock>
```

使い方は簡単ですが、シンタックスとか記法に納得するのが大変かも。でも個人的には使ってみたいです。

https://github.com/110chang/riot-test

[ブログにも掲載しました](http://110chang.com/knowledge/riot-gulp-browserify/)