データ取得
ルートが有効化された時にサーバーからデータを取得する必要がしばしばあります。例えば、ユーザープロフィールを描画する前に、サーバーからユーザーデータを取得する必要があります。これを実現するためには 2 種類の方法があります。
ナビゲーション後の取得: ナビゲーションを先に実行し、その後次に入ってくるコンポーネントのライフサイクルフック内でデータを取得します。データ取得中にローディングを表示します。
ナビゲーション前の取得: ルートに入るガード内でナビゲーション前にデータ取得をします。そして、データ取得後にナビゲーションを実行します。
技術的にはどちらも正当な選択肢です。究極的にはあなたが目指しているユーザーエクスペリエンスに依存します。
ナビゲーション後の取得
このアプローチを取る時は次に来るコンポーネントが即座にナビゲーションされ、描画されます。そして、コンポーネントの created
フックの中でデータを取得します。この方法ではネットワーク越しにデータを取得している間にローディング状態を表示する機会があります。また、各 view に対して、異なるローディングの対応をすることもできます。
$route.params.id
を元にポストのデータを取得する必要がある Post
コンポーネントを想定してみましょう。
<template>
<div class="post">
<div class="loading" v-if="loading">
Loading...
</div>
<div v-if="error" class="error">
{{ error }}
</div>
<div v-if="post" class="content">
<h2>{{ post.title }}</h2>
<p>{{ post.body }}</p>
</div>
</div>
</template>
export default {
data () {
return {
loading: false,
post: null,
error: null
}
},
created () {
// view が作られた時にデータを取得し、
// そのデータは既に監視されています
this.fetchData()
},
watch: {
// ルートが変更されたらこのメソッドを再び呼び出します
'$route': 'fetchData'
},
methods: {
fetchData () {
this.error = this.post = null
this.loading = true
// `getPost` をあなたのデータ取得用 util や API ラッパーに置き換えてください
getPost(this.$route.params.id, (err, post) => {
this.loading = false
if (err) {
this.error = err.toString()
} else {
this.post = post
}
})
}
}
}
ナビゲーション前の取得
こちらのアプローチでは新しいルートへ実際にナビゲーションする前にデータを取得します。次に入ってくるコンポーネント内の beforeRouteEnter
ガードでデータ取得を実行できます。データ取得が完了したら next
を呼ぶだけです。
export default {
data () {
return {
post: null,
error: null
}
},
beforeRouteEnter (route, redirect, next) {
getPost(route.params.id, (err, post) => {
next(vm => vm.setData(err, post))
})
},
// コンポーネントが既に描画されている際のルート変更時は
// ロジックが少し異なります
beforeRouteUpdate (to, from, next) {
this.post = null
getPost(to.params.id, (err, post) => {
this.setData(err, post)
next()
})
},
methods: {
setData (err, post) {
if (err) {
this.error = err.toString()
} else {
this.post = post
}
}
}
}
次に入ってくる view へのリソースを取得している間、ユーザーは前の view に滞在します。したがって、データ取得中にプログレスバーや何らかの指標を表示することをオススメします。また、もしデータ取得が失敗した場合、何かグローバルな警告メッセージのようなものを表示する必要があります。