如何使用 Firebase“onSnapshot”侦听器值更新 Vue“ref”?

Posted

技术标签:

【中文标题】如何使用 Firebase“onSnapshot”侦听器值更新 Vue“ref”?【英文标题】:How to update a Vue "ref" with Firebase "onSnapshot" listener values? 【发布时间】:2022-01-11 11:04:47 【问题描述】:

我有一个使用 Firebase onSnapshot 监听器的 Vue 组合。

当该侦听器上的数据发生更改时,我希望它更新名为 documentsArrayref

当我 console.log documentsArray inside onSnapshot 函数时,它似乎正在工作,因为它包含一个值数组。但是当我 console.log outside onSnapshot 函数时,数组是空的。

为什么会这样?

onSnapshot 函数外部的 console.log 也应该包含值数组。

这是我的可组合(我正在使用 TypeScript):

import  ref, Ref, watchEffect  from "vue";
import  projectFirestore  from "@/firebase/config";
import 
  collection,
  query,
  orderBy,
  onSnapshot,
  DocumentData,
  Timestamp,
 from "firebase/firestore";

interface Document 
  id: string;
  message: string;
  name: string;
  createdAt: Timestamp;


const getCollection = (
  collectionString: string
): 
  documentsArray: Ref<Document[] | null>;
  error: Ref<string | null>;
 => 
  const documentsArray = ref<Document[] | null>(null);
  const error = ref<string | null>(null);
  const colRef = collection(projectFirestore, collectionString);
  const colRefOrdered = query(colRef, orderBy("createdAt"));

  const unsubscribe = onSnapshot(
    colRefOrdered,
    (snap) => 
      const results: Document[] = [];
      snap.docs.forEach((doc: DocumentData) => 
        doc.data().createdAt && //Ensures the server timestamp has been added
          results.push(
            ...doc.data(),
            id: doc.id,
          );
      );
      documentsArray.value = results;
      console.log("documentsArray.value inside snapshot", documentsArray.value); //<-- This works. It prints an array of documents.
      error.value = null;
    ,
    (err) => 
      console.log(err.message);
      documentsArray.value = null;
      error.value = "could not fetch data";
    
  );
  watchEffect((onInvalidate) => 
    onInvalidate(() => 
      unsubscribe();
    );
  );
  console.log("documentsArray.value outside snapshot", documentsArray.value); //<-- This does not work. It prints an empty array.
  return  documentsArray, error ;
;

export default getCollection;

【问题讨论】:

【参考方案1】:

onSnapshot 回调中的代码是异步运行的(在运行回调之外的代码之后),为了查看函数外部的更改,您必须创建一个观察程序来查看更改:

import import  ref, Ref, watchEffect, watch  from "vue";

....
  const unsubscribe = onSnapshot(
    colRefOrdered,
    (snap) => 
      ...
  );

watch(documentsArray,(newVal,oldVal)
  console.log("documentsArray.value outside snapshot", documentsArray.value);

,deep:true)

【讨论】:

感谢这有助于为我指明正确的方向。但我希望外部 console.log 工作的真正原因是因为 getCollection 可组合返回 documentsArray 并带有 null 值。那么如何重新配置​​可组合以使用watch 并返回更新后的数组呢? IE。通过const documentsArray, error = getCollection("messages"); 在另一个文件中调用此可组合项时,我希望documentsArray 包含一个值。 @TinyTiger 你的可组合返回 documentsArray 这是反应性的,所以你可以在外面使用 watchcomputed,虽然最后的 console.log 只会被执行一次此时数组仍为空。 谢谢!使用您上面提供的代码让它工作!但是我在调​​用可组合的文件中使用了watch。非常感谢您的帮助:)

以上是关于如何使用 Firebase“onSnapshot”侦听器值更新 Vue“ref”?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Firebase onSnapshot 中使用 .catch

firebase onSnapshot 如何刷新数组以避免重复键?

等待 onSnapshot 获取数据

Firebase firestore onSnapshot 在 useEffect 中无法正常工作

Firebase onSnapshot函数上的无限循环正常吗?

cleanup() 在使用 Firebase Firestore onSnapshot 的 useEffect() 中不起作用