vue-router
でちょっとつまづいた点をまとめます。
遭遇したバグ
SPA サイトのサイドバーに設置したrouter-link
をクリックしても反応せず、ページが更新されない。
挙動をチェック
OKな挙動
[特集ページ] を表示中にサイドバーからタグリンクをクリック
-> 対象のタグを選択した [タグ検索ページ] に遷移する
NGな挙動
[タグ検索ページ] を表示中にサイドバーから別のタグリンクをクリック
-> クリックが反応せずコンテンツが切り替わらない
上記より、どうやら「同じページでパラメーターが異なる場合」に、リンクがうまく動かないようであることがわかりました。
バージョン情報
- macOS Sierra
- vue 2.2.x
- vue-router 2.5.x
原因
アタリもつきますし、ドキュメントを読めば一発で原因がわかる内容でした。
router設定は次です。
1{
2 path : '/book/tag/:id',
3 component: require('./components/Book/List.vue')
4}
pathの :id
のように、 vue-routerのコロンから始まる部分が、いわゆる動的セグメント
です。
動的セグメントで受け取ったパラメーターは、Vueコンポーネントで次のように受け取ります。
1// components/Book/List.vue
2export default {
3 created() {
4 this.fetchItems(this.$route.params.id)
5 },
6 :
7}
ドキュメントには、動的ルートマッチングでは コンポーネントの再利用をおこなうため、ライフサイクルフックが呼ばれない ということがしっかりと記載されています。
ルートのパラメーターを使う際に特筆すべき点は、ユーザーが /user/foo から /user/bar へ遷移するときに同じコンポーネントインスタンスが再利用されるということです。 両方のルートが同じコンポーネントを描画するため、古いインスタンスを破棄して新しいものを生成するよりも効率的です。しかしながら、これはコンポーネントのライフサイクルフックが呼ばれないことを意味しています。
vue-router 2 > 基本的な使い方 > 動的ルートマッチング > パラメーター変更の検知
http://router.vuejs.org/ja/essentials/dynamic-matching.html
今回の不具合はまさにこの「コンポーネントの再利用」によるもので、パラメーター変更を検知していなかったためでした。
対処方法
ドキュメント記載の通り、パラメーターの変更をwatchします。
1watch: {
2 '$route' (to, from) {
3 // ルートの変更の検知...
4 }
5}
具体的には次のようなコードとしました。
コード中の + が、今対応の追記部分です。
1// components/Book/List.vue
2export default {
3 created() {
4 this.fetchItems(this.$route.params.id)
5 },
6 data() {
7 return {
8 books: []
9 }
10 },
11+ watch: {
12+ '$route' (to, from) {
13+ this.fetchItems(to.params.id)
14+ }
15+ },
16 methods: {
17 fetchItems(id) {
18 http.get('book/cat/'+ id, res => {
19 this.books = res.data.books
20 })
21 }
22 }
23}
まとめ
vue-routerで動的ルートマッチングを行う場合、「対象コンポーネントを表示中にパラメーターが変化する」場合はwatchしましょう。
私の場合、サイドバーからのリンクが上記に当てはまりましたが、TOPページからは通常通り遷移するので発見が遅れてしまいました。
デバッグ不足でしたー。