ルートナビゲーションを✅
「7時間」気合のタスキを巻いていたおかげで少し可処分時間を確保する事ができた23期スバルです。現在heroku run rails db:migrateをすると、一生エラーが出る状況に陥っています。
Mysqlのエラーかと思いきや、Dockerのエラーかもしれないぽい。
ちょっと厳しめなので、バブる場所を模索中な今日この頃です。
さて、今回は、ナビゲーションガードを使って画面遷移時の挙動を制御する方法を学んでいきたいと思います。
ナビゲーションガードとは
リダイレクトもしくはキャンセルによって遷移をガードするために主に使用されるvue-routerのメソッド。
ログイン済みのユーザーからしかアクセスできないページを実装したい時などに使われる
下記のように使われている。
router.beforeEach((to, from, next) => {
if (to.name !== 'Login' && !isAuthenticated) next({ name: 'Login' })
else next()
})
vue-routerのindex.jsに書くことで、どのコンポーネントでも適用されるようにしている。
今回の例を直訳すると、「次の遷移先のコンポーネント名がLoginではない、そしてユーザーがisAuthentivatedではない場合、Loginページにリダイレクトされる」ことを指している。
つまり、ログイン中のユーザーでない場合はログインページにリダイレクトされるということ。
データ取得
このナビゲーションを応用して使うことで、画面遷移時の最初の動作を制御し、ライフサイクルフックの流れに合わせて画面で行われる挙動をアレンジすることができる。
$route.params.id
を元にアルコール詳細のデータを取得する必要がある Alcohols コンポーネントを想定してみる。
ナビゲーションの前後で取得方法が変わるそうで。下記参考文献から引用。
- ナビゲーション後の取得: ナビゲーションを先に実行し、その後次に入ってくるコンポーネントのライフサイクルフック内でデータを取得します。データ取得中にローディングを表示します。
- ナビゲーション前の取得: ルートに入るガード内でナビゲーション前にデータ取得をします。そして、データ取得後にナビゲーションを実行します。
<template>
<div class="alcohol">
<div v-if="loading" class="loading">
Loading...
</div>
<div v-if="error" class="error">
{{ error }}
</div>
<div v-if="alcohol" class="content">
<h2>{{ alcohol.name }}</h2>
<p>{{ alcohol.description }}</p>
</div>
</div>
</template>
<script>
export default {
data() {
return {
loading: false,
alcohol: null,
error: null
}
},
created() {
# view が作られた時にデータを取得する
this.fetchData()
},
watch: {
# ルートが変更されたらこのメソッドを再度呼び出している
$route: 'fetchData'
},
methods: {
fetchData() {
this.error = this.alcohol = null
this.loading = true
#最初はloadingをtrueにしておく。
axios.get(`alcohol/#{this.route.params.id}`, (err, alcohol) => {
#Promiseベースのデータ取得が実行されている。
this.loading = false
#取得できたらloadingが消える。
if (err) {
this.error = err.toString()
} else {
#データを取得できたら、alcoholにデータを入れる
this.alcohol = alcohol
}
})
}
}
}
</script>
アルコールの詳細画面を作りたい時に使う事ができる。
this.$route.params.idで、渡されたidをURLから取得。
取得に成功したら、loadingをfalseにし、取得したaloholデータをdataに格納する処理を、非同期で行なっている。
ナビゲーション前の取得
こちらのアプローチでは新しいルートへ実際にナビゲーションする前にデータを取得している。
次に入ってくるコンポーネント内の beforeRouteEnter
ガードでデータ取得を実行する事ができる。データ取得が完了したら next
を呼ぶだけで、遷移したい先に飛ぶ事ができる。
export default {
data() {
return {
alcohol: null,
error: null
}
},
#ここで使う!
beforeRouteEnter(route, redirect, next) {
axios.get(`alcohol/#{route.params.id}`, (err, alcohol) => {
next(vm => vm.setData(err, alcohol))
})
},
// コンポーネントが既に描画されている際のルート変更時は
// ロジックが少し異なります
beforeRouteUpdate(to, from, next) {
this.alcohol = null
axios.get(`alcohol/#{route.params.id}`, (err, alcohol) => {
this.setData(err, alcohol)
next()
})
},
methods: {
setData(err, alcohol) {
if (err) {
this.error = err.toString()
} else {
this.alcohol = alcohol
}
}
}
}
現在の心境
もうMYSQLが嫌いになりそう。サーバーサイドエンジニアを目指しているとは到底思えない言動ですが。とりあえず下記エラーを攻略してMysqlと仲直りしたいです。。
ActiveRecord::ConnectionNotEstablished