Riot.jsのv2からv3でいろいろ修正・変更されたもの

[Riot.js Advent Calendar 2016](http://qiita.com/advent-calendar/2016/riotjs)の9日目です！

[Riot.js](http://riotjs.com)（以下riot）は非常にシンプルかつ軽量で敷居も低く、とても書きやすいコンポーネント指向のUIライブラリです。（ここまでテンプレート）

# v2からv3への移行する際の注意点

公式サイトの[Migration from riot 2](http://riotjs.com/guide/migration-from-riot2/)に詳細な内容が書かれていますので、そちらを読んでいただく方が早いと思いますので、ここでは単に列挙だけします。
（※[日本語訳](http://riotjs.com/ja/guide/migration-from-riot2/)も出てます！）

1. `riot-tag`属性の廃止、`data-is`属性を使う
  - `data-is`はネストしたタグでも使用可能
  - また動的なテンプレート変数(expression)にも対応

2. スペースが入った`observable`のイベントは動作しない
3. `id, name`属性でのDOMの参照を廃止、`ref`属性を使う
  - 参照する場合は`this.refs.hoge`と書く（後でもうちょっと触れます）
4. オブジェクトの`each`メソッドによるループの書き方が`value, key in object`に変更
5. `riot.route`が本体から分離しスタンドアローンのライブラリ化
  - 別途npmなりcdnなりで[riot-route](https://github.com/riot/route)を持ってくる必要がある
  - 書き方例：`riot.route.start()` → `route.start()`
6. `mount`の前に`update, updated`イベントは発火しない
  - タグをマウント前に調整したい場合は`before-mount, mount`を利用
  - `update, updated`はタグのアップデートの実行時のみ
7. 自動`preventDefault`の廃止
8. 子タグで発生したイベントで、親タグをアップデートしない
9. （`observable`について）半角スペース区切りでイベント名を複数指定できない
  - メソッドチェーンで各イベントを一つずつトリガーする
  - その代わり速度は6倍速くなった！！
10. Scoped CSSがデフォルトに
11. `babel 5.8`にはもう対応しない（使っている方のみ対象）

# その他変更点
自分でも追ってみたんですが、v2でも修正されているものもたくさんありました。詳しくは[リリースノート](http://riotjs.com/release-notes/)をご参照下さい。（※自分が見つけていないものもあるかもしれませんので、見つけ次第更新します！）

### ▼動的にロードされた子タグは親タグオブジェクトに入らない
コードを見ていただきましょう。

```html:app.tag
<app>
  <h2> { opts.title } </h2>
  <div id="tgt"></div>

  <script>
    this.on('mount', function() {
      riot.mount('#tgt', 'child-tag')
      console.info(this.tags)
    })
  </script>
  <style>
    :scope h3 { 
      color: #4E88CC;
      float: left;
    }
  </style>
</app>

<child-tag>
  <h3>It's child tag!</h3>
</child-tag>
```

```js:マウント
riot.mount('*', { title: 'Parent tag' })
```

上記を実行すると、consoleの出力結果に`child-tag`タグは含まれません。では`app`タグ内を以下のように変更してみます。


```html:修正版appタグ

<app>
  <h2> { opts.title } </h2>
  <div data-is="{ subComponent }"></div>

  <script>
    this.on('mount', function() {
      this.subComponent = 'child-tag'
      this.update()  // 明示的にupdateを実行しないとchild-tagが反映されません
      console.info(this.tags)
    })
  </script>
  <style>
    :scope h3 { 
      color: #4E88CC;
      float: left;
    }
  </style>
</app>
```

これを実行すると、今度はconsoleに`Object {child-tag: ee}`と表示されたと思います。v3では、動的にロードされた子タグも`this.tags`で取得できるようになってました。

# 不具合？
個人的に使ってみて、これは不具合じゃないかな？と思ったものを書きていきます。（※今後アップデートで再現しなくなる可能性もありますので、その都度更新したいと思います）

### ▼ versionが取れない
~~現在利用しているのriotのバージョンを取得するには、`riot.version`と書けばよかったですが、v3からはこれでは取得できません。どうすれば良いかもわからないため、ソース本体を参照すればド頭に書いてありますのでそれ見てます。~~

![スクリーンショット 2016-12-08 14.55.34.png](https://qiita-image-store.s3.amazonaws.com/0/48034/90a1fe22-4c12-78c3-9e7f-d67b61bf10b5.png)

__※2017/04/09 追記__
`v3.3.2`の時点で修正され、従来通り`riot.version`で取得できます！


### ▼ `ref`属性でも参照できないケースがある

v3からはDOMに`id, name`属性に代わって`ref`属性を付けて、JavaScriptでは`this.refs.名前`で参照するように変わりましたが、以下のような場合は参照できません。

```html:refでのDOMの参照
<app>
  <!-- layout -->
  <h3>{ opts.title }</h3>

  <div ref="hoge">hoge</div>
  <div>
    <input type="text" ref="fuga" value="fuga">
  </div>

  <!-- javascript -->
  <script>
    console.info(this.refs.hoge.innerText)  // ここでエラー（undefined）になる！
    console.info(this.refs.fuga.value)      // 上をコメントアウトしても、ここも同じエラーになる
  </script>  
</app>
```

これの対策は、`script`タグ内を以下のように書き換えると参照できます。

```html:修正版
<script>
  this.on('mount', function() {
     console.info(this.refs.hoge.innerText)
     console.info(this.refs.fuga.value)
  })
</script>
```

上記で分かるように、イベントハンドラのコールバック関数内では問題なく参照できます。（`onclick`など、他のものでも同様）


### ▼ `each`ループ内ではifメソッドが機能しない
v2では動作していた以下のコードがv3では機能しませんでした。（※issue [#2133](https://github.com/riot/riot/issues/2133)にて修正されてました）

```html

<app>
  <!-- layout -->
  <h3>Collection with if</h1>
    <div each={ item, i in items } if={i == 2}> { item.name + (i+1) } </div>

    <!-- 'show'だと動作します。
      <div each={ item, i in items } show={i == 2}> { item.name + (i+1) } </div>
     -->
  </h3>

  <!-- javascript -->
  <script>
    this.items = [
    	{name: "one"},
      {name: "two"},
      {name: "three"},
      {name: "four"},
      {name: "five"},
      {name: "six"}
    ];
  </script>  
</app>
```



# 終わりに
公式サイトにv2からv3への移行についてしっかり注意点が書いてありますので、皆さんv3を使ってみて下さい(ﾟ∀ﾟ)~~だいぶ薄っぺらい内容になってしまった。。。~~

明日は @cognitom さんによる[ES6で書くRiot - Felt編](http://qiita.com/cognitom/items/fedcfe08bf5527e43bcb)です！