Help us understand the problem. What is going on with this article?

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

More than 3 years have 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の機能のほんの一部分です。
ルーティング処理や、イベント周りを全然追えて追えていない状況ですので、薄っぺらい内容になってしまいましたが、シンプルさが伝わってもらえれば幸いです。

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

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away