vue-routerでちょっとつまづいた点をまとめます。

遭遇したバグ

[技術書サイト]のサイドバーに設置したrouter-linkをクリックしても反応せず、ページが更新されない。


宣伝:技術書サイトはこちらでーす。

ITエンジニアのための技術書レビューサイト(仮) 技術書Yome
https://book-yome.net/


挙動をチェック

OKな挙動

[特集ページ] を表示中にサイドバーからタグリンクをクリック
  -> 対象のタグを選択した [タグ検索ページ] に遷移する

NGな挙動

[タグ検索ページ] を表示中にサイドバーから別のタグリンクをクリック
  -> クリックが反応せずコンテンツが切り替わらない

上記より、どうやら「同じページでパラメーターが異なる場合」に、リンクがうまく動かないようであることがわかりました。

バージョン情報

  • macOS Sierra
  • vue 2.2.x
  • vue-router 2.5.x

原因

アタリもつきますし、ドキュメントを読めば一発で原因がわかる内容でした。

router設定は次です。

{
  path     : '/book/tag/:id',
  component: require('./components/Book/List.vue')
}

pathの :id のように、 vue-routerのコロンから始まる部分が、いわゆる動的セグメントです。

動的セグメントで受け取ったパラメーターは、Vueコンポーネントで次のように受け取ります。

// components/Book/List.vue
export default {
  created() {
    this.fetchItems(this.$route.params.id)
  },
  :
}

ドキュメントには、動的ルートマッチングでは コンポーネントの再利用をおこなうため、ライフサイクルフックが呼ばれない ということがしっかりと記載されています。

ルートのパラメーターを使う際に特筆すべき点は、ユーザーが /user/foo から /user/bar へ遷移するときに同じコンポーネントインスタンスが再利用されるということです。 両方のルートが同じコンポーネントを描画するため、古いインスタンスを破棄して新しいものを生成するよりも効率的です。しかしながら、これはコンポーネントのライフサイクルフックが呼ばれないことを意味しています。
vue-router 2 > 基本的な使い方 > 動的ルートマッチング > パラメーター変更の検知
http://router.vuejs.org/ja/essentials/dynamic-matching.html

今回の不具合はまさにこの「コンポーネントの再利用」によるもので、パラメーター変更を検知していなかったためでした。

対処方法

ドキュメント記載の通り、パラメーターの変更をwatchします。

watch: {
    '$route' (to, from) {
      // ルートの変更の検知...
  }
}

具体的には次のようなコードとしました。
コード中の + が、今対応の追記部分です。

// components/Book/List.vue
export default {
  created() {
    this.fetchItems(this.$route.params.id)
  },
  data() {
    return {
      books: []
    }
  },
+ watch: {
+   '$route' (to, from) {
+     this.fetchItems(to.params.id)
+   }
+ },
  methods: {
    fetchItems(id) {
      http.get('book/cat/'+ id, res =>  {
        this.books = res.data.books
      })
    }
  }
}

まとめ

vue-routerで動的ルートマッチングを行う場合、「対象コンポーネントを表示中にパラメーターが変化する」場合はwatchしましょう。

私の場合、サイドバーからのリンクが上記に当てはまりましたが、TOPページからは通常通り遷移するので発見が遅れてしまいました。
デバッグ不足でしたー。

この記事はtomita@atuwebがお届けしました。