Posted at
Riot.jsDay 13

jQuery使いがRiot.jsを使ってみた話

More than 1 year has passed since last update.

この記事はRiot.js Advent Calendar 2016の13日目の記事です。

前日の方と同じようなテーマになってしまって申し訳ないです!

普段はCakePHPでのサイト構築やNode.jsでWebAPIプログラムを書いたりしてます。

フロントではjQueryしか使わない、JavaScriptフロントエンドライブラリ経験1ヶ月程度のゆるふわな感想ですので、生暖かく見守っていただければ幸いです。


きっかけ


  1. Node.jsで動いてるWebAPI(戻りはJSON)をWebブラウザでモニタリングする機能をサクッと作れないかなー

  2. PHPならサクッと組めるけどNode.jsを運用しているサーバにPHPを新たに入れるのは嫌だなー

  3. jQueryでDOM操作して書くのも大変だよなー(実際やったけど可読性最悪でメンテがしんどかった)

  4. そうだ、JavaScriptのフロントエンドライブラリを使ってみよう!


jQueryはすごく便利だが…

jQueryを極めたかどうかは別として、jQueryである程度コードを書けるようになると、「jQueryと水さえあれば生きていける!!」状態になります(個人の感想です)。

先日、JavaScriptのアドベントカレンダーの方に投稿したネイティブJavaScriptとjQueryの比較をしてみて、改めてjQueryの便利さを再認識した次第です。

しかしながらjQueryオンリーでの極度なDOM操作はしんどいものです。書き始めた時はぷよぷよで連鎖を重ねる如く、メソッドチェインを繋げることに快感を覚えるんですが、ファイルを閉じたら最後、次の日見てみたらなんじゃこりゃー!!!ってなります(ました)。jQueryのメソッドチェインは「ダイヤキュート」ぐらいに留めておき、間違っても「ばよえ~ん」を詠唱しないように心がけるべきです。

と、どうでもいい前置きは置いておいて、前々から気になっていたJavaScriptフロントエンドライブラリを使ってみることにしました。


はじめはAngularJSを使っていた

JavaScriptのフロントエンドライブラリの二大巨頭といえば「AngularJS」と「React」のようです。ぐぐってもだいたいこの2つが上位に出てきます。一方はフルスタックのフレームワーク、もう一方はView特化型のUIライブラリ。どちらにしようか悩んだ挙句、とりあえずGoogleが作ってるし使ってみるか、ということでAngularJS(1系)を使ってみました。

なるほど、何から何まで揃っていてこりゃ便利だ。

しかしAngularJSはフルスタックのフレームワークなだけあり覚えることも多く、ツール的なものを作るには少々持て余す感じでした。

例えて言うならば、近所のコンビニにジュース買いに行くのに車で行く感じ?

正直そんな大掛かりなものは要らないですし、近所のコンビニにジュースを買いに行く程度なら徒歩かよくても自転車です。

そんなこんなで別のライブラリも試してみようということになり、色々調べているうちに以下の記事に辿り着きました。

フロント界隈で一番イケてるのは AngularJS でも React でもなく Riot.js だという話

そこで、Riot.jsに興味を持ち、公式サイトのよくある質問と答えに大変痺れるお言葉が…


IE8をなんでサポートしないの?

やっと、この低品質ブラウザを無視しても大丈夫になりました。


よくぞ言ってくれた!!この言葉を待っていた!!!!!

というわけで、Reactをすっ飛ばしてとりあえず使ってみることにしました!


Riot.jsのよいと思ったとこ


直観的に書ける

たった1ファイル(Riot.js+インブラウザコンパイラ)読み込ませるだけで、HTMLファイルが一般的なテンプレートエンジンのように早変わり。見た目上はほぼHTML+JavaScriptで、AnglureJSのような独特なディレクティブも少なく、直観的に書けるのは素晴らしいと思います。

条件分岐ならif、繰り返しならeach、イベントに至っては昔ながらのonXXXX(onclickなど)そのまんまですね。

{}で囲まれたのがテンプレート変数、この変数はまんまJavaScriptなので関数をかませたりももちろんできます。

<test></test><!-- ここに出力される -->

<!-- Riot.js+インブラウザコンパイラを読み込む -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/riot/2.6.7/riot+compiler.js"></script>

<!-- 実処理内容(外部ファイルにすることも可。ここではインラインで書く) -->
<script type="riot/tag">
<test>

<!-- テンプレートとなる部分 -->
<table>
<tr each={num in numbers}>
<td>{num}</td>
</tr>
</table>
<!-- /テンプレートとなる部分 -->

// 処理となる部分:START
this.numbers = [1,2,3];
// 処理となる部分:END

</test>
</script>

<script>
// testタグをマウントして実行
riot.mount('test');
</script>


コンポーネント指向

パーツごとに管理できるというのがいいですね。

上の例ですと、testタグがひとつのパーツであると考えられます。

しかもタグごとにHTML,JavaScript,CSSを独立したファイルとしてまとめておけるのでこれまた便利。


シンプル イズ ベスト

Riot.jsには必要最小限の機能しかありません。標準機能で出来ることは標準機能に任せるという思想みたいです。

必要最低限の機能しかないということは、Riot.jsの自体の学習コストが低い、標準機能で実装したコードは他に使いまわせる(仮にRiot.jsを使わなくなった場合のコストも低くなるハズ)などのメリットが考えられます。

たとえば、WebAPIのデータを取得するために必要なAjax通信ですが、Riot.jsにはその機能がありません。


え?じゃあjQueryのような外部ライブラリ入れるか、あの原始的なXMLHttpRequestで書かないとダメなの???


いいえ、違います。

まだ実験段階ではありますがFetch APIなんて便利な機能がいつの間にか標準APIとして提供されつつあるんですね。

お疲れさまXMLHttpRequest、こんにちはfetch



しかもこのAPIはPromiseを返してくれるのですごく扱いやすい。

※ Promiseって慣れるとホント便利です…手前味噌ですが、

約束って面倒くさい。


jQueryも使えますよ

Riot.js FAQ

ただし、DOM操作はRiot.jsに任せて、イベントデリゲートやプラグインの活用のみに限定した方がよさそうです。


Riot.jsで惜しいなと思ったとこ


テキスト整形機能が欲しい

ある程度作りこむとなると、AngularJSのfilter機能的なものが欲しくなります。

サーバ側で取得してきたデータをそのまま無加工で表示できればいいんですが、実際はそういうわけにもいかないことが多いと思います。(特に日時データとか)

それに加え、JavaScriptにはマトモなテキスト整形機能がありません。

せめて日付フォーマットの整形機能があってもいい気がするんですが、それすらありません。

AngularJSだと以下のようなコードで日付フォーマット整形ができます。


AngularJS

{{current_date|date:'yyyy/M/d hh:mm'}}


Riot.jsでは自前で関数を書いて実現します。

※フォーマット出力すると大変なのでとりあえず固定フォーマットで


Riot.js

<test>

{date(current_date)}
date(date_string) {
let date = new Date(date_string);
let y = date.getFullYear();
let m = ("0"+(date.getMonth()+1)).slice(-2);
let d = ("0"+date.getDate()).slice(-2);
let h = ("0"+date.getHours()).slice(-2);
let i = ("0"+date.getMinutes()).slice(-2);
return `${y}/${m}/${d} ${h}:${i}`;
}
</test>

Viewに特化しているからこそ、こういう機能は欲しいと思いました。


資料が圧倒的に少ない

日本語はともかく、英語の資料もあまりないような…?

自分の検索の仕方が悪いだけ?


実際書いてみた

JSONを取得して表示するだけのコードです。

<!DOCTYPE html>

<html>
<head>
<title>json monitor</title>
<meta charset="UTF-8">
<script src="//cdnjs.cloudflare.com/ajax/libs/riot/2.6.7/riot+compiler.js"></script>
</head>
<body>
<json-monitor></json-monitor>
<script type="riot/tag">
<json-monitor>
<span if={error != ''}>{error}</span>
<table if={error == ''}>
<tr>
<th>ID</th>
<th>名前</th>
<th>更新時間</th>
</tr>
<tr each={data in datas}>
<td>{data.id}</td>
<td>{data.name}</td>
<td>{conv_datetime(data.modified)}</td>
</tr>
</table>
this.error = '';
// APIからJSONデータを取得
fetch('/api/hoge.json')
.then((data) => {
return data.json();
})
.then((datas) => {
this.update({datas});
})
.catch((error) => {
this.update({error});
});
// 日付変換メソッド
conv_datetime(date_string) {
let date = new Date(date_string);
let y = date.getFullYear();
let m = ("0"+(date.getMonth()+1)).slice(-2);
let d = ("0"+date.getDate()).slice(-2);
let h = ("0"+date.getHours()).slice(-2);
let i = ("0"+date.getMinutes()).slice(-2);
return `${y}/${m}/${d} ${h}:${i}`;
}
</json-monitor>
</script>
<script>
riot.mount('json-monitor');
</script>
</body>
</html>


/api/hoge.json

[{"id":1,"name":"hoge","modified":"2016-12-12 10:00:00"},{"id":2,"name":"fuga","modified":"2016-12-13 10:00:00"}]


これだけのコード量で完結するんだからすごい。

※実際はリクエストURLにパラメータを与えたり、ちゃんと例外処理書いたり、レイアウト整えるためにCSSとか書かないとダメですが。

JSONは(当然ですが)JavaScriptと相性いいのでサクサク書けるのはいいですね。

ちなみに自環境で動けばいいツールでしたので、レガシーなWebブラウザじゃ動かないと思います!


さいごに

今回触れたのはRiot.jsの機能のほんの一部分です。

ルーティング処理や、イベント周りを全然追えて追えていない状況ですので、薄っぺらい内容になってしまいましたが、シンプルさが伝わってもらえれば幸いです。

ちょうど空きがありましたので、明日も引き続き書かせていただきます!