現時点、いいねを加えるところだけ実装しました。
公式のドキュメントがStarだったのでコードはstarですが、やってることは「いいね」です。
ぜひこの記事を読み始める前に、まずいいねを押してからみていただけると幸いです。
今回公式のドキュメントを解読した項目としては
・フィールドの数値に1を加算(いいねを+1)すること
・フィールドの配列に要素を追加すること
([0,1]→[0,1,2]みたいな)
環境
VueCLI
Postには、post_idが1から順に数字を振っています。便利。
前半では、postsコレクション内の指定したpost(実際にフロントでクリックするポスト)に対して、starCountを1増やすと言う処理になっています。
後半は、現在ログインしているユーザーのstarCountドキュメントに、starをつけたポストのID(数字)を配列にして入れます。
なぜ配列にするかというと、ドキュメントの読み込み数が減ると思ったからです。
こういう設計の点でのアドバイスは24時間マジで受け付けてます。よろしくお願いします。
actions: {
addStarCount({ getters ,commit }, postId){
if(getters.uid){
firebase.firestore().collection("posts").where('post_id', '==', postId).get().then(doc => {
var data = doc.docs[0].id;
firebase.firestore().collection("posts").doc(data).update({
starCount: firebase.firestore.FieldValue.increment(1)
})
})
firebase.firestore().collection(`users/${getters.uid}/starCount`).doc("starCount").update({
star_post_id: firebase.firestore.FieldValue.arrayUnion(postId)
})
commit('addStarCount')
}
},
}
*postIdには、コンポーネント側でポストのIDを渡します。
ドキュメントを指定して、updateをする。
starCount: firebase.firestore.FieldValue.increment(1)
↑でデータベース上の数値に+1する。()内の数値が1億だったらアクションが発動するたびに1億加算される
star_post_id: firebase.firestore.FieldValue.arrayUnion(postId)
↑ユーザーがスターをつけたポストのIDが配列になってどんどん追加されていく。
data() {
return {
userStarCounts: [],
}
}
created() {
firebase.firestore().collection(`users/${this.$store.getters.uid}/starCount`).doc('starCount').get().then(doc => {
this.userStarCounts = (doc.data().star_post_id)
})
配列の呼び出しは上記のとおり。
良い名前が思いつかなかった。
userStarCountsに、現在ログイン中のユーザーが「いいね」したポストのIDが全て入っています。
次はいいねを消す処理。
deleteStarCount({ getters, commit }, postId){
if(getters.uid){
firebase.firestore().collection("posts").where('post_id', '==', postId).get().then(doc => {
var data = doc.docs[0].id;
firebase.firestore().collection("posts").doc(data).update({
starCount: firebase.firestore.FieldValue.increment(-1)
})
})
firebase.firestore().collection(`users/${getters.uid}/starCount`).doc("starCount").update({
star_post_id: firebase.firestore.FieldValue.arrayRemove(postId)
})
commit('deleteStarCount')
}
},//deleteStarCountここまで
starCount: firebase.firestore.FieldValue.increment(-1)
さっきは1だったのは−1にしてスターが減る
star_post_id: firebase.firestore.FieldValue.arrayRemove(postId)
arrayRemoveで、「数字が全く同じやつを配列から削除」できるようです。
ここで、完成したと思って一旦データベース削除してクリアな状態にしてからいいねを押してみたらエラーを吐いた。
##実は1ヶ所ダメなところあります。
どこでしょうか。
ユーザーのstarCountドキュメントにポストを配列でアップデートして追加していくのですがupdateはあくまで「更新」であって、作成とかは含まれないらしいのです。
そこで出てきたのが.setというやつ。
###じゃあそのまま.updateを.setにすると、追加ではなく新規にポストidが1個しかない配列に置き換わってしまう
のでした。
ということで、正解は
firebase.firestore().collection(`users/${getters.uid}/starCount`).doc("starCount").set({
star_post_id: firebase.firestore.FieldValue.arrayUnion(postId)
},{ merge: true})
最後にmerge:trueをつけることにより、想定の通り「今の配列に追加」を実装することができます。
便利。
##フロント側の最善が思いつかなかった
ポストをそれぞれ子コンポーネントにすることによって、「いいね」の増減を子コンポーネントで実装してます。
<template>
<div v-if="userStarCounts.includes(post.post_id)">
<v-icon v-show="likedDrawer" color="pink accent-2grey" @click="deleteStar(post.post_id)">mdi-heart</v-icon>
<v-icon v-show="!likedDrawer" color="grey lighten-2" @click="addStar(post.post_id)">mdi-heart</v-icon>
</div>
<div v-else>
<v-icon v-show="likedDrawer" color="grey lighten-2" @click="addStar(post.post_id)">mdi-heart</v-icon>
<v-icon v-show="!likedDrawer" color="pink accent-2grey" @click="deleteStar(post.post_id)">mdi-heart</v-icon>
</div>
</template>
data() {
return {
starCount: 0,
userStarCounts: [],
likedDrawer: true,
}
},
created() {
firebase.firestore().collection(`users/${this.$store.getters.uid}/starCount`).doc('starCount').get().then(doc => {
this.userStarCounts = (doc.data().star_post_id)
})
},
methods: {
addStar(postId){
this.addStarCount(postId)
this.starCount ++
this.likedDrawer = !this.likedDrawer
},
deleteStar(postId){
if(confirm('削除しますか?')){
this.deleteStarCount(postId)
this.starCount --
this.likedDrawer = !this.likedDrawer
} else{
alert("削除は取り消されました");
}
},
}
これで一応実装できました。
が、もっと良いコードが存在すると思います。
vuexだとstateが全てのポストに適用なので、配列とかフィールドとかをmutationsでコミットしないと実装できないので、今回はコンポーネントでゴリ押しました。
v-ifとv-showのところは伸び代しかないので、ご指導ご鞭撻よろしくお願いします。