【反旗を翻せ!】
「Riot.js」入門ハンズオン!
@omiend
●自己紹介
●自己紹介
@omiend
サーバーサイドエンジニア(Scala )
最近はReactばかり書いてます
●映画好き
ものごころがついた時から
●洋楽好き
奥さんはライブ会場でゲット LINKINPARK RHCP*
●ジョギング好き
人間に必要なもの
=一人になる時間+音楽を聴く時間+運動する時間
=あ、ジョギング!
=しかもプライスレス!
●Riot.jsとは
●Riot.jsとは
関連するHTMLとJavaScriptを結合し、再利用可能なコンポーネントとし
てまとめたカスタムタグを利用してアプリケーションを構築することが
できる、超軽量Webフレームワークです。
オフィシャルサイトに詳しい説明があります。
http://riotjs.com/ja/
●カスタム・タグ
Viewと対になるScriptを、一つのタグに定義したものです。
HTML
Custom Tag
HTML
<p>{this.hoge}</p>
Script
let name = ‘hoge’
Custom Tag
HTML
Script
●デモ
http://omiend.github.io/riotjs_todo/
●どこがカスタムタグなの?
●コンパイラ
インブラウザ・コンパイルとプリコンパイルから選べます。
私は普段、Webpackでプリコンパイル(&トランスパイル)させて、
BundleされたJSを読み込むようにしています。
このハンズオンでは環境構築を簡素化するために、表示時にコンパイル
されるインブラウザ・コンパイルを採用しています。
オフィシャルサイトにより詳しい説明があります。
http://riotjs.com/ja/api/compiler/
●ルーティング
ルーティングにはriot.routeを利用します。
下記アクションでURLが変更されると、与えられたcallback関数を実行
します。
1.新しいURLが、ブラウザのロケーションバーに入力されたとき
2.ブラウザの戻る/進むボタンが押されたとき
3.route(to)が呼び出されたとき
4.アンカータグ<a>がクリックされたとき
●ルーティング
当TODOアプリにおいては、URLの変更を検知→URLの状態を受け取り、
callback関数にてカスタム・タグをマウントさせています。
// 例えば、‘todo/1000/edit’にアクセスすると
// collection=‘todo’; id=‘1000’; action=’edit’がバインドされる
riot.route(function(collection, id, action){
riot.mount('route', collection || 'home', {id: id})
})
●ルーティング
参考までに、私は普段riot-routerを利用しています。
riot-router
https://github.com/gabrielmoreira/riot-router
こちらも気になっています。
riot-routehandler
https://github.com/crisward/riot-routehandler
●ハンズオン!
●このハンズオンの注意点
独学なので、Riot.jsのお作法に則っていない可能性があります
お作法がアレば、の話ですが
乱暴にお手軽に実装しています
Global変数をそのまま触ってます(良くない)
observableを利用して、fluxを取り入れるべきだなぁとは感じています
●このハンズオンの注意点
ローカル環境においては、カスタムタグを外部ファイルとして読み込む
ため
<script type="riot/tag" src="tags/home.tag"></script>
●このハンズオンの注意点
Google Chromeで起動すると下記のエラーが発生し、正常に動作しない
可能性があります。
riot+compiler.min.js:2 XMLHttpRequest cannot load file://hoge-
hoge/riotjs_todo/tags/home.tag. Cross origin requests are only
supported for protocol schemes: http, data, chrome, chrome-
extension, https, chrome-extension-resource.
その際は、Google Chrome起動時に`--allow-file-access-from-files`を
引数を指定して起動するか、Firefoxなどの別のブラウザでお試し下さい。
●このハンズオンの注意点
Python(MacOSならば標準搭載)を利用し、SimpleServerを利用する
手もあります。
知らなかったPythonのSimpleServer
http://omiend.hatenablog.jp/entry/2016/09/13/203000
$ cd riot_todo
$ python -m SimpleHTTPServer
●ローカル環境で動かしましょう
- https://github.com/omiend/riotjs_todo
- Zipダウンロード → 解凍
git clone git@github.com:omiend/riotjs_todo.git でもどうぞ
- index.htmlをブラウザで開く
●構成
.
├── css
│ ├── main.css // ページの整形用に
│ ├── normalize.css // https://necolas.github.io/normalize.css/
│ └── skeleton.css // わたくしomiendが好きな、軽量CSSフレームワークです( http://getskeleton.com/)
├── images
│ └── riotjs.png // riotをイメージした画像
├── index.html // ブラウザが一番初めに読み込む単純なHTMLファイルです
├── scripts
│ └── app.js // ルーティングと、予め登録されたデータを格納しています
└── tags // カスタム・タグを配置しているディレクトリです
├── add.tag // TODOデータの追加を行うカスタム・タグです
├── commands.tag // TODOデータに対して何らかの処理を行うコマンドを集めたカスタム・タグです
├── edit.tag // TODOデータを更新するためのフォームが定義されたカスタム・タグです
├── home.tag // ホーム画面を表示するための簡単なHTMLが定義されたカスタム・タグです
├── navi.tag // ナビバーの単純なHTMLが定義されたカスタム・タグです
└── todo.tag // TODOデータを一覧したりなど、TODOアプリの基盤画面を定義したカスタム・タグです
●/index.html
ブラウザで一番初めに読み込むファイルです。
内容は単純なHTMLですが、下記の要素が定義されています。
// カスタムタグがマウントされるセレクター 名称はrouteでなくても良いです
<route></route>
// Riot.js本体と、コンパイラをCDNで読み込み
<script src="https://cdn.jsdelivr.net/riot/2.6/riot+compiler.min.js"></script>
// ルーティングなどの読み込み
<script src="scripts/app.js" defer></script>
●tag/navi.tag
こちらは本当に単純なHTMLです。
コメントアウトを解除し、画面にナビバーが表示されることを確認して
ください。
正しく表示されていれば、naviタグが正しくマウントされているという
ことです。
●tag/home.tag
ルーティング設定によって、「/」にアクセスされた時に<route>にマウ
ントされるタグです。
同タグ内のScriptにて‘Riot.js’という値を返す関数「echo()」が定義され
ています。
「<h5>I Love {this.echo()} !</h5>」にて当該関数を実行し、
‘Riot.js’を受け取ってレンダリングしています。
単純な例ですが、カスタム・タグの基本がわかると思います。
●tag/todo.tag
TODOアプリケーションの基盤的なカスタム・タグです。
まず、riotが提供するeachによってTODOデータをループし、表示して
います。
<div class="row" each={todo in store.todos}>
●tag/todo.tag
一行ごとにcommandsタグをマウントさせています。
commandsタグはtodoという名前を引数として、ループ中のtodoを受け
取っています。
<commands todo={todo}></commands>
●tag/commands.tag
todoタグから受け取ったTODOデータは、optsというriotが提供する特別
な変数に格納されます。
optsは、Reactで言う所のpropsのイメージです。
<div if={opts.todo.done}> // doneがtrueだったらレンダリング
●tag/commands.tag
commandsタグは、TODOデータに対してアクションを行うボタンを提
供するために実装したカスタム・タグです。
- editTagを<route>にマウントさせるために呼び出される関数。
- フラグを更新する関数。
- TODOデータを削除する関数を定義しています。
一つのカスタム・タグが、各行で各TODOデータのみを利用する動きと
なっており、コンポーネントの再利用を意識した作りとしています。
●tag/add.tag
addタグがマウントされる<add>はtodoタグ内に定義されているので、
addタグは子タグと呼べます。
子タグは親タグ(todoタグ)がマウントされた後に初期化されます。
HTML
親
HTML
Script
子
●tag/add.tag
TODO内容を入力し、ADDボタンがクリックされると、addタグに定義
されたadd関数が実行され、storeに入力内容を保存します。
実はその後の「store.trigger('refresh')」が大切な処理です。
●tag/add.tag
「store.trigger(‘refresh’)」はapp.jsにてstoreをobservableのオブ
ジェクトとしており、add実行時にtriggerを実行することによって
'refresh'イベントを発火させています。
// storeの変更を監視できるように、Observableに登録する
riot.observable(store)
●tag/add.tag
storeに対する'refresh'イベントが発火されると、todoタグに定義された
下記のcallback関数が実行され、todoタグが自身を更新し、TODO一覧
に追加したTODOデータが表示されるという仕組みになっています。
var self = this // callbackの中でtodoタグを参照するため
store.on('refresh', function(){
self.update() // todoタグを更新
})
●tag/add.tag
オブザーバブル(Observable)についてはこちらをご参照ください。
http://riotjs.com/ja/api/observable/
●tag/edit.tag
commandsタグからリクエストパラメータでTODOデータのIDを受け
取っているくらいです。
コメントアウトを解除して、更新画面が表示されることを確認してくだ
さい。
riot.route(function(collection, id){
riot.mount('route', collection || 'home', {id: id})
})
edit() {
riot.route(`edit/${opts.todo.id}`)
}
opts.form = store.todos.filter(function(s){return s.id == opts.id})[0]
●参考にさせていただいたモノ
●参考にさせていただいたモノ
オフィシャルサイト
http://riotjs.com/ja/
割りとドキュメントが充実してます。
●参考にさせていただいたモノ
オフィシャルのソースレベルの実装例集
https://github.com/riot/examples
英語がわからなくても、ソースコードならば・・・!
●参考にさせていただいたモノ
martinmuzatkoさんのチートシートなど
http://martinmuzatko.github.io/riot-cheatsheet/
http://happy-css.com/lessons/riotjs/
オフィシャルサイトの内容から更に踏み込んだ内容です。
●参考にさせていただいたモノ
Qiitaのタグ
http://qiita.com/tags/riot
●ありがとうございました

Riotjsハンズオン