環境
Vue.js 2.6.11
Rails 6.1.3
修正する部分
質問の解決ステータスを表すステータスブロックと回答数が周りに比べて少し遅れて表示されてしまっています。
このままだと少し気持ち悪いので同タイミングで表示されるように修正します。
また、ページネートの< >もちらついているのでそれも解消しようと思います。
構成
質問カードの構成は、
QuestionBase.vue
---QuestionCommetnsCount.vue
---QuestionStatus.vue
とステータスブロックと回答数の部分は周りに対して子要素となっています。
また、ステータス部分の判定は、
①axiosでそれぞれの質問にベストアンサーがあるかをaxiosで取得
②あればbestAnswerに代入、なければエラーに分岐
③v-ifでbestAnswerがあれば解決済み、なければ回答受付中を表示
となっています。
<template>
<div>
<div
v-if="bestAnswer"
>
解決済
</div>
<div v-else>
回答受付中
</div>
</div>
</template>
<script>
import axios from "axios";
export default {
props: ["question"],
data: function () {
return {
bestAnswer: "",
};
},
created() {
axios
.get(`/api/v1/bestanswer/${this.question.id}`)
.then((response) => {
this.bestAnswer = response.data;
console.log(response.data);
})
.catch((error) => {
console.log(error);
});
},
};
</script>
なぜ表示タイミングがずれているのか?
ライフサイクルを確認してみます。
親要素のmountが終わってから、子要素のcreatedが始まっているのが確認できました。
これが原因で表示の時間差が起こっているようです。
解決方法
周りに比べて表示が遅れる
emitを使って、子要素のcreatedが終わったタイミングで親要素にそれぞれtrueを渡しています。
両方揃ったタイミングで、同時にレンダリングされるようになります。
またここで、v-ifを使うとそもそも子要素のcreatedが行われず表示がされなくなるので注意です。
(内部の子要素も動作しないため)
<script>
...
created() {
axios.get(`/api/v1/comments_count/${this.question}`).then((response) => {
this.count = response.data;
this.$emit("isCountCreated", true);
});
</script>
<script>
...
created() {
axios.get(`/api/v1/bestanswer/${this.question.id}`).then((response) => {
this.bestAnswer = response.data;
this.$emit("isStatusCreated", true);
});
</script>
<template>
<div v-show="isCountCreated && isStatusCreated">
...
</template>
ステータスが表示されてから切り替わる
質問ステータスが、解決済のものも一瞬「解答受付中」が表示されてから「解決済」に切り替わっていました。
これに関しても、上記の解決方法と同様にaxiosに
this.isStatusCreated = true
を仕込んでおき
<div v-if="isStatusCreated">
としておけば解決です。