LoginSignup
6
1

More than 3 years have passed since last update.

Riot Route でルーティング時のレンダリング前に何らかの処理をさせる手っ取り早い方法

Last updated at Posted at 2020-01-01

本記事は Riot.js Advent Calendar 2019 の第22日目です.

以下, 注意事項です.

  • Riot.jsriot と呼ぶ
  • @riotjs/routeroute と呼ぶ
  • 本記事の route は v5.2.0(執筆時点の最新) とする ※v5 については別途記事を書き中 :bow:

onBeforeRoute イベントハンドラの生成

route のソースコードを見ていくと, 2つ riot コンポーネントが見つかりますが, その中の route-hoc.riot を見てみますと,

router-hoc.riotの抜粋
onBeforeRoute(path, pathToRegexp) {
  if (!match(path, this.state.pathToRegexp)) {
    this.update({
      route: null
    })
  }
},

何やら嬉しい名前のメソッドが定義されていますw また, index.js の中を見てみますと,

index.js
// 省略
import Route from './components/route-hoc.riot'
import Router from './components/router-hoc.riot'
// 省略
export {
  // 〜
  Router,
  Route
}

ふむふむ🤔よくわからないが, 使われているのは確かですね. では上手いことこの onBeforeRoute を使ってみましょう.

差し込み処理の追加

今回は公式のデモの一つ standalone-history.html をお借りします. <router>, <route> などのタグベースではなく, JS ベースでのルーティングの実装ですね.

standalone-history.html(変更前)
<nav>
  <a href="/hello">Hello</a>
  <a href="/user">User</a>
  <a href="/user/gianluca">Username</a>
  <a href="/goodbye">goodbye</a>
</nav>
<div id="root"></div>
<script type="module">
  const { initDomListeners, setBase } = route

  const loc = window.location

  setBase(`${loc.protocol}//${loc.host}`)

  const onRoute = (url) => root.innerHTML = `${url} and params=${JSON.stringify(url.params)}`

  route.route('/hello').on.value(onRoute)
  route.route('/user').on.value(onRoute)
  route.route('/user/:username').on.value(onRoute)
  route.route('/goodbye').on.value(onRoute)

  initDomListeners()
</script>

nav にリンクが並んでいるだけの簡単な SPA で, クリックすると対応したテキストが下の div タグに表示されます.

ではこちらに onBeforeRoute メソッドを追加していきます.

standalone-history.html(変更後)

  <nav>
    <a href="/hello">Hello</a>
    <a href="/user">User</a>
    <a href="/user/gianluca">Username</a>
    <a href="/goodbye">goodbye</a>
  </nav>
  <div id="root"></div>
  <script type="module">
    const { initDomListeners, setBase } = route

    const loc = window.location

    setBase(`${loc.protocol}//${loc.host}`)

    const onRoute = (url) => root.innerHTML = `${url} and params=${JSON.stringify(url.params)}`
+   const onBeforeRoute = () => {
+     // 現在のルーティングパスを取得し表示
+     alert(route.getCurrentRoute())
+   }

+   route.route('/hello').on.value(onBeforeRoute)
    route.route('/hello').on.value(onRoute)
    route.route('/user').on.value(onRoute)
    route.route('/user/:username').on.value(onRoute)
    route.route('/goodbye').on.value(onRoute)

    initDomListeners()
  </script>

では実行してみましょう.

127_0_0_1_8080_の内容_と_Standalone_History_Demo.png

先に Username リンクをクリックしており, div タグには /user/gianluca のテキストが表示されています. ここで Hello リンクをクリックしたものが↑のキャプチャになります.

alert で表示されるテキストは /hello となっており, Hello のルーティングそのものは実行されていますが, まだテキストは書き換わっていないため, レンダリングはブロックされています.

おわりに

あくまでこれは簡易的な方法で, 実際にはこれではダメだと思っています…というのも, 先程の処理を以下のように書き換えると, 先に onRoute!! のアラートが表示されます.

抜粋
-    const onRoute = (url) => root.innerHTML = `${url} and params=${JSON.stringify(url.params)}`
+    const onRoute = (url) => {
+      root.innerHTML = `${url} and params=${JSON.stringify(url.params)}`
+      alert("onRoute!!")
+    }
   const onBeforeRoute = () => {
     // 現在のルーティングパスを取得し表示
     alert(route.getCurrentRoute())
   }

-   route.route('/hello').on.value(onBeforeRoute)
    route.route('/hello').on.value(onRoute)
+   route.route('/hello').on.value(onBeforeRoute)

これはちょっと細かい話をすると, route は内部的には rawth というライブラリを使っており1 , さらに rawth は内部的には erre というライブラリに依存しています.

で, この子は .on で検知するルーティングを配列で管理しており, 順番に実行されるため, 先に onRoute!! が表示される形となります. ですので, route.route('/hello')セットする順番を先に書く必要があります.

本当は正しい使い方があると思いますが, 一旦これで動いているのでまた何か分かったら更新したいと思います.

ではでは(=゚ω゚)ノ

参考


  1. 厳密には route のコア機能はほぼ全てこの子の機能 

6
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
1