Riot.js Advent Calendar 2016の9日目です!
Riot.js(以下riot)は非常にシンプルかつ軽量で敷居も低く、とても書きやすいコンポーネント指向のUIライブラリです。(ここまでテンプレート)
v2からv3への移行する際の注意点
公式サイトのMigration from riot 2に詳細な内容が書かれていますので、そちらを読んでいただく方が早いと思いますので、ここでは単に列挙だけします。
(※日本語訳も出てます!)
-
riot-tag
属性の廃止、data-is
属性を使う
-
data-is
はネストしたタグでも使用可能 - また動的なテンプレート変数(expression)にも対応
- スペースが入った
observable
のイベントは動作しない -
id, name
属性でのDOMの参照を廃止、ref
属性を使う
- 参照する場合は
this.refs.hoge
と書く(後でもうちょっと触れます)
- オブジェクトの
each
メソッドによるループの書き方がvalue, key in object
に変更 -
riot.route
が本体から分離しスタンドアローンのライブラリ化
- 別途npmなりcdnなりでriot-routeを持ってくる必要がある
- 書き方例:
riot.route.start()
→route.start()
-
mount
の前にupdate, updated
イベントは発火しない
- タグをマウント前に調整したい場合は
before-mount, mount
を利用 -
update, updated
はタグのアップデートの実行時のみ
- 自動
preventDefault
の廃止 - 子タグで発生したイベントで、親タグをアップデートしない
- (
observable
について)半角スペース区切りでイベント名を複数指定できない
- メソッドチェーンで各イベントを一つずつトリガーする
- その代わり速度は6倍速くなった!!
- Scoped CSSがデフォルトに
-
babel 5.8
にはもう対応しない(使っている方のみ対象)
その他変更点
自分でも追ってみたんですが、v2でも修正されているものもたくさんありました。詳しくはリリースノートをご参照下さい。(※自分が見つけていないものもあるかもしれませんので、見つけ次第更新します!)
▼動的にロードされた子タグは親タグオブジェクトに入らない
コードを見ていただきましょう。
<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>
riot.mount('*', { title: 'Parent tag' })
上記を実行すると、consoleの出力結果にchild-tag
タグは含まれません。では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からはこれでは取得できません。どうすれば良いかもわからないため、ソース本体を参照すればド頭に書いてありますのでそれ見てます。
※2017/04/09 追記
v3.3.2
の時点で修正され、従来通りriot.version
で取得できます!
▼ ref
属性でも参照できないケースがある
v3からはDOMにid, name
属性に代わってref
属性を付けて、JavaScriptではthis.refs.名前
で参照するように変わりましたが、以下のような場合は参照できません。
<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
タグ内を以下のように書き換えると参照できます。
<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にて修正されてました)
<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編です!