是否可以在 Vue 应用程序中呈现 Firebase 数据的实时变化?

Posted

技术标签:

【中文标题】是否可以在 Vue 应用程序中呈现 Firebase 数据的实时变化?【英文标题】:Is it possible to render real-time changes in Firebase data within a Vue app? 【发布时间】:2019-08-24 10:38:55 【问题描述】:

我在 Vue 应用程序中使用 Firebase 进行身份验证和数据库。我正在开发的组件会监听特定用户的“朋友”集合中的变化。

我只想在实时反映数据库更改的同时显示朋友列表。

到目前为止,我采取了两种方法,都导致成功捕获更改的相同问题,但无法在 dom 中显示更改。

方法一

在 created() 函数中,我使用 .onSnapshot() 函数添加我的侦听器。这成功地捕获了数据库中的更改。但是,如果我将 this.friends 设置为更新后的值,屏幕不会改变。

方法2

使用 Vuex 加载好友列表。我为商店创建了一个监视功能,可以成功跟踪更改。但是在这个手表功能中更改this.friends也不会更新屏幕。

对简单变量的反应按预期工作。

<template>
  <v-container fluid>
     friends 
  </v-container>
</template>

<script>
import db from '@/firebase/firestore'
import firebase from 'firebase'

export default 
  name: 'Test',
  data() 
    return 
      friends: []
    
  ,
  created() 
    let firebaseUser = firebase.auth().currentUser
    let ref = db.collection('users')
    ref.where('user_id', '==', firebaseUser.uid).limit(1).get()
    .then( snapshot => 
      if (snapshot.docs[0].data()) 
        db.collection("users").doc(snapshot.docs[0].id)
        .onSnapshot(function(doc) 
          let user = doc.data()
          console.log('friends', user.friends) // outputs correctly
          this.friends = user.friends // does not update dom
        )
      
    )
  ,

</script>

【问题讨论】:

【参考方案1】:

您可以按如下方式设置监听器:

<template>
   <v-container fluid>
       friend 
   </v-container>
</template>

<script>
import db from '@/firebase/firestore'
import firebase from 'firebase'

export default 
  name: "Test",
  data() 
    return 
      friend: null
    ;
  ,
  created() 
    const firebaseUser = firebase.auth().currentUser
    const ref = db.collection('users')

    ref
      .where('user_id', '==', firebaseUser.uid)
      .limit(1)
      .onSnapshot(querySnapshot => 
         let f = querySnapshot.docs[0].data();
         f.id = querySnapshot.docs[0].id;
         this.friend = f;
      );
  
;
</script>

<style>
</style>

仅供参考,如果要删除.limit(1) 并显示所有friends,请执行以下操作:

<template>
  <v-container fluid>
    <template v-for="f in friends">
      <div> f.id </div>
    </template>
  </v-container>
</template>

<script>
import db from '@/firebase/firestore'
import firebase from 'firebase'

export default 
  name: "Test",
  data() 
    return 
      friends: []
    ;
  ,
  created() 
    const firebaseUser = firebase.auth().currentUser
    const ref = db.collection('users')

    ref
      .where('user_id', '==', firebaseUser.uid)
      .onSnapshot(querySnapshot => 
        var fArray = [];
        querySnapshot.forEach(doc => 
          let f = doc.data();
          f.id = doc.id;
          fArray.push(f);
        );
        this.friends = fArray;
      );
  
;
</script>

<style>
</style>

【讨论】:

感谢@renaud-tarnec,您的解决方案已经奏效。似乎我的方法有第二个嵌套异步调用,它影响了反应性。通过简化调用,它按预期更新。非常感谢!【参考方案2】:

如果你使用 Vuex,你是否使用 Vuex,那么首先你必须在 Computed Property 中导入 getter,否则如果你不使用 Vuex,你必须观察正在变化的数据。 您必须观看 Computed Property Remember 组件将仅重新渲染数据属性更改,如果数据更改然后 vue 知道该组件中的某些更改,它将重新渲染该组件 您必须按照以下答案为您提供解决方案 Watching Computed Property in Vue

【讨论】:

感谢您的意见。我确实尝试过以这种方式使用 Vuex,它在输出到控制台时有效,但没有触发重新渲染。基于 renaud-tarnec 代码,似乎像我一样嵌套 firebase 调用会导致反应性问题。感谢您的意见!

以上是关于是否可以在 Vue 应用程序中呈现 Firebase 数据的实时变化?的主要内容,如果未能解决你的问题,请参考以下文章

bootstrap-vue 组件呈现为注释

Vue Router 无法正常工作并添加了 #

Vue 模板未在 for 循环中呈现

Vue.js:为啥我的单文件组件没有在我的模板中呈现/显示

Vue - 如何在 Vue 组件中呈现 HTML

是否有推荐的 Vue JS 应用程序 API 和 Vuex 设计模式