[riot: SPA by riot-route] Implement SPA routing by riot with riot-route. #riot #js
表示するビューをJS側フレームワークで頑張る。親タグの下に複数の子タグをマウントする準備をしておいて、リクエスト(正確にはブラウザのアドレス変更検知)をルータが振り分けてマウントする子タグを選別するような感じ。
riotjs の外部ライブラリ。2系では標準で入ってたのに3から外部あつかい。別途npmでインストールして app.js とかで import してやる。使うときは .tag ファイル内で requre('riot-route') 的な?
考え方として、エントリーJSにRouting情報(ベースURLやURLパターンによるマウントタグとマウント先DOM要素ID指定などなど...)を書いておき、表示するタグを切り替えるような使い方をする。SPAは通常アプリケーションのどあたまからJSで成り立つので、初回に全ビューのJSをimportして仮想DOMをエントリーJSでくみ上げておき、各タグは表示された時のことだけ考える。
https://github.com/riot/route https://github.com/riot/route/tree/master/doc https://github.com/bourbonizable/riot-routing-sample
$ npm install --save riot-route
// app.js
import route from 'riot-route'
// ***.tag
const route = require('riot-route')
// app.js (entry)
import riot from 'riot'
import route from 'riot-route'
import content_a from './content_a.tag'
import content_b from './content_b.tag'
document.addEventListener('DOMContentLoaded', function(){
riot.mount('*') //mount static tags
// common routing settings
route.start()
route.base('/')
// routing each tags
route('/content/a', (...args) => {
riot.mount('#content', 'content-a');
})
route('/content/b', (...args) => {
riot.mount('#content', 'content-b');
})
})
/**
* route()
*/
route(function(collection, id, action) {
// URLが変更されると
// 与えられたcallbackを実行
})
route('/fruit/*', function(name) {
console.log('The detail of ' + name)
// URLが`/fruit/apple`に変更した場合
// 'apple'を`name`として渡す
})
route('/old..', function() {
console.log('The pages under /old was moved.')
// /oldと/old/**/**の両方に一致させたいときは .. でok
})
// リダイレクト的なこともできる
route('customers/267393/edit', 'エディットページ(タイトル)')
/**
* route.start()
*/
route.stop() // 古いコールバックを解除
route.start() //URL変更の検知を開始(再起動)
// 通常は riot の読み込みと同時に自動で行われる...らしいよ
/**
* route.create()
*/
var subRoute = route.create()
subRoute('/fruit/apple', function() { /* */ })
// http://riotjs.com/ja/api/route/#ルーティング・グループ
// http://riotjs.com/ja/api/route/#ルーティングの優先度
/**
* subRoute.stop()
*/
var subRoute = route.create()
subRoute('/fruit/apple', function() { /* */ })
subRoute.stop() //サブ・ルータを停止し全コールバックをクリア
/**
* route.exec()
* URLを変更せず別タグをその場で実行(非推奨)
*/
route.exec(function(collection, id, action) {
//現在のURLを調べて、与えられたcallback
//URL変更なしに「その場で」実行(非推奨だよ)
})
/**
* route.query()
* URLからパラメータを取り出す
*/
route('/search..', function() {
var q = route.query()
console.log('Search keyword: ' + q.keyword)
console.log('Search limit: ' + q.limit)
})
/**
* route.base()
* ルーティングベースパスを変更
* デフォルトは #
*/
route.base('/app')
// http://riotexample.com/app/fruit/apple みたいなとき
// /fruit/appleの部分だけをルーティングに指定
/**
* route.parser()
* デフォルトパーサを変更
*/
// 例えばこんな !/user/activation?token=xyz のをパスに含みたい
route.parser(function(path) {
var raw = path.slice(2).split('?'),
uri = raw[0].split('/'),
qs = raw[1],
params = {}
if (qs) {
qs.split('&').forEach(function(v) {
var c = v.split('=')
params[c[0]] = c[1]
})
}
uri.push(params)
return uri
})