Firestoreのデータをリアルタイムに表示するためにはFirestoreのonSnapshot関数を使って(公式ドキュメント参照 こちら)リアルタイムにデータの変更を読み取る必要があります
firebase.jsの142行目~180行目がその内容です
142行目でインポートをして利用します
143行目のインポートはVue3のライフサイクルのonUnmounted関数です
onSnapshotを使用すると、データの読み取りの状態が継続されます
当然読み取りが必要なくなれば解除をする必要があります
もう一度呼び出せばデタッチとなり、読み取り後の処理は行われなくなります
177行目のonUnmounted(unsubscribe)の部分です
この場合、読み取りを行うコンポーネントがUnmountedされる際にデタッチをして読み取りごのコールバックを停止しています
onSnapshot()の使い方
公式のドキュメントに詳しく書いていますが、このコード内で何を行っているかを説明しておきます
export const updateStockItems = () => {… return ~}
そとから処理の結果を呼び出せるようにしています
必要となるコンポーネントからこの関数を呼び出し、更新されたデータ、またはコンポーネントの最初の呼び出し時のデータをコンポーネントに返してクライアント側で利用できるようにしています
そのデータを格納するための配列のstockItemsを設定してreactiveを利用して、変更されたデータをリアルタイムにクライアントで処理できるようにしています
簡単に説明すると、本来であればデータが更新されたらそれに伴ってDOMの操作を行って、表示する内容を変更するという処理がクライアント側で必要になります
関連する場所が多くなるとかなり面倒な作業になります
Vueのreactiveやrefを利用すると、DOM操作を行わずに更新されたデータを反映することができます
詳しくはVueのreactiveをご確認ください
146行目のconst q = query(collection(db, “stockItems”));でデータベースの参照先を指定しています
何らかのデータの絞り込みを行う場合はここでwhereを利用しますが、今回は特に絞り込みが必要ではないため使っていません
collection(db, “stockItems”)の部分で使用するデータベース(dbの設定自体はfirebase.jsの14行目const db = getFirestore()で設定済み)のコレクションのstockItemsを参照しています
collection関数も当然インポートしてつかいます
147行目のconst unsubscribe = onSnapshot(q, (snapshot) => {…}でデータの読み取りを行い、そのコールバック関数を書き込んでいます
qはさきほどの参照先、今回であればstockItemsコレクションのデータを読み取っています
snapshotはデータベースのデータが格納されているデータオブジェクトです
何らかのデータの変更があった際にここの()=>{}のコールバック関数の処理が行われます
148行目の snapshot.docChanges().forEach((change) => {…}
の部分でsnapshotがもつdocChanges()を利用して、データベースにどのような変更があったかを読み取るようにしています
そして、その変化の種類がchangeの中に入っています
それをデータごとに読み取って配列化されたデータをforEachでそれぞれ処理を繰り返しています
149行目のif (change.type === “added”) {}以降でそれぞれの変更の種類に応じた処理を行っています
addedはデータベースに追加があった場合、また、最初に呼び出された際のスナップショットのデータすべてを読み取ります
stockItems.push({…change.doc.data()})
の部分で、あらかじめ用意しておいたデータ格納用の配列stockItemsにデータを一つずつpushで追加して配列のデータを作成しています
これで空っぽだったstockItemsにデータが入った状態になります
ということで、コンポーネントの表示の際、Stockitems.vueの25行目でupdateStockItemsを呼び出して初期の読み取りをすれば、そのタイミングでのデータの読み取りができます
読み取ったデータをtableDataに格納して、templateのel-tableタグ(element+のテーブルコンポーネント)のdataプロパティにv-bind(:data=””というところ)を利用してデータをel-tableに渡してデータを表示しています
もちろんデータ量が多い場合は工夫が必要です
addedによって初期状態のデータがすべて読み取るのは、最初のスナップショットとの差分でデータ更新を読み取る仕組みだからです
詳しくは、公式のドキュメントを参照してください
データ更新時の処理
155行目~162行目までの
if (change.type === “modified”) {…}の部分がデータ更新時(上書きでの変更など)の処理になります
変更される前のデータであるstockItemsの配列データに対してforEachで一つずつデータの検証をおこないます
ここで実行しなければならないのは、クライアント側で持っているstockItemsの配列データにFirestoreのデータベースの変更を反映することです
function(item, index) {…}でそれぞれのデータについてどのように処理をしていくかをかいています
itemは配列の中の1つのデータが格納されています
forEachで一つずつのデータを連続で処理していくので、
1番目のデータ、2番目のデータとデータを変更していく必要があります
そのデータがはいっているのがitemになります
indexは配列のインデックスです(要するに何番目のデータか)
if(item.itemId===change.doc.data().itemId){stockItems[index] = change.doc.data()}
の部分で変更があったデータが配列のどこに(何番目)に含まれているかを検証しています
change.doc.data().itemIdには変更のあったドキュメントのデータがかくのうされています
.itemIdの部分で、変更のあったデータのitemIDを参照して、配列のデータと一致するところを探しています
ヒットしたらそのデータの配列番号を指定して、配列データをstockItems[index] = change.doc.data()の部分でFirestoreの変更データであるchange.doc.data()のデータで上書きしています
これで、クライアントが持つデータ配列が更新されて、あとは、リアクティブにせっていしているため、クライアントの処理は自動で行われ、在庫数が反映されるようになっています
コメント