【问题标题】:how to display spinner when data is being fetched from cloud firestore in vuejs?从 vuejs 中的云 Firestore 获取数据时如何显示微调器?
【发布时间】:2019-07-19 00:37:45
【问题描述】:

我也在使用 vuex 开发 firebase 和 vuejs。所以在 onauthStateChanged() 方法中,我尝试获取所有数据形式的帖子集合。它需要一些时间来显示,同时我想显示微调器,它指定正在加载某些东西的用户。

我试过了,它的工作很酷,但是代码的问题是

  <loadingSpinner v-if="loading"></loadingSpinner>
                <div v-if="posts.length">
                    <div v-for="post in posts" v-bind:key=post.id class="post">
                        <h5>{{ post.userName }}</h5>
                        <span>{{ post.createdOn | formatDate }}</span>
                        <p>{{ post.content | trimLength }}</p>
                        <ul>
                            <li><a @click="openCommentModal(post)">comments {{ post.comments }}</a></li>
                            <li><a @click="likePost(post.id, post.likes)">likes {{ post.likes }}</a></li>
                            <li><a @click="viewPost(post)">view full post</a></li>
                        </ul>
                    </div>
                </div>
                <div v-else>
                    <p class="no-results">There are currently no posts</p>
                </div>

Spinner 组件负责旋转动画:

<loadingSpinner v-if="loading"></loadingSpinner>

下面的 html 代码用于显示来自 firebase 的数据

posts 和 loading 变量是来自 vuex 状态的计算属性

问题是当重新加载页面时,微调器显示在

<div v-else>
     <p class="no-results">There are currently no posts</p>
</div>

我想在加载微调器时限制 v-else 条件。

顺便说一下,加载计算属性是一个布尔值,它基于 onAuthstateChanged() firebase 方法做出反应

这是我的整个 vuex 存储文件:

    import Vue from 'vue'
import Vuex from 'vuex'
const fb = require('./firebaseConfig.js')

Vue.use(Vuex)

// handle page reload
fb.auth.onAuthStateChanged(user => {
    if (user) {
        store.commit('setCurrentUser', user)
        store.dispatch('fetchUserProfile')

        fb.usersCollection.doc(user.uid).onSnapshot(doc => {
            store.commit('setUserProfile', doc.data())
        })

        // realtime updates from our posts collection
        fb.postsCollection.orderBy('createdOn', 'desc').onSnapshot(querySnapshot => {
            // check if created by currentUser
            let createdByCurrentUser
            if (querySnapshot.docs.length) {
                createdByCurrentUser = store.state.currentUser.uid == querySnapshot.docChanges[0].doc.data().userId ? true : false
            }

            // add new posts to hiddenPosts array after initial load
            if (querySnapshot.docChanges.length !== querySnapshot.docs.length
                && querySnapshot.docChanges[0].type == 'added' && !createdByCurrentUser) {

                let post = querySnapshot.docChanges[0].doc.data()
                post.id = querySnapshot.docChanges[0].doc.id

                store.commit('setHiddenPosts', post)
            } else {
                store.commit('setLoading', true)
                let postsArray = []
                querySnapshot.forEach(doc => {
                    let post = doc.data()
                    post.id = doc.id
                    postsArray.push(post)
                })     
                store.commit('setPosts', postsArray)
                store.commit('setLoading', false)
            }
        })
    }
})

export const store = new Vuex.Store({
    state: {
        currentUser: null,
        userProfile: {},
        posts: [],
        hiddenPosts: [],
        loading: true
    },
    actions: {
        clearData({ commit }) {
            commit('setCurrentUser', null)
            commit('setUserProfile', {})
            commit('setPosts', null)
            commit('setHiddenPosts', null)
        },
        fetchUserProfile({ commit, state }) {
            fb.usersCollection.doc(state.currentUser.uid).get().then(res => {
                commit('setUserProfile', res.data())
            }).catch(err => {
                console.log(err)
            })
        },
        updateProfile({ commit, state }, data) {
            let name = data.name
            let title = data.title

            fb.usersCollection.doc(state.currentUser.uid).update({ name, title }).then(user => {
                // update all posts by user to reflect new name
                fb.postsCollection.where('userId', '==', state.currentUser.uid).get().then(docs => {
                    docs.forEach(doc => {
                        fb.postsCollection.doc(doc.id).update({
                            userName: name
                        })
                    })
                })
                // update all comments by user to reflect new name
                fb.commentsCollection.where('userId', '==', state.currentUser.uid).get().then(docs => {
                    docs.forEach(doc => {
                        fb.commentsCollection.doc(doc.id).update({
                            userName: name
                        })
                    })
                })
            }).catch(err => {
                console.log(err)
            })
        }
    },
    mutations: {
        setLoading(state, payload){
            state.loading = payload
        },
        setCurrentUser(state, val) {
            state.currentUser = val
            // console.log(val)
        },
        setUserProfile(state, val) {
            state.userProfile = val
            // console.log(val)
        },
        setPosts(state, val) {
            if (val) {
                state.posts = val
            } else {
                state.posts = []
            }
        },
        setHiddenPosts(state, val) {
            if (val) {
                // make sure not to add duplicates
                if (!state.hiddenPosts.some(x => x.id === val.id)) {
                    state.hiddenPosts.unshift(val)
                }
            } else {
                state.hiddenPosts = []
            }
        }
    },
})

有什么建议吗?

【问题讨论】:

  • 您应该共享您的整个 vuex 代码 + 您的整个组件代码,因为要解决您的问题,您必须从异步任务中“驱动”/控制微调器显示。换句话说,当您开始查询时,您会显示微调器,一旦 Firebase 请求的承诺得到解决,您就会隐藏微调器。
  • 我更新了我的问题
  • 我认为在您的代码(来自本教程savvyapps.com/blog/…)中有您需要的一切来满足您的需求:您应该使用store.commit('setLoading', true)store.commit('setLoading', false)来控制微调器.我建议您详细学习本教程并尝试根据您的需要进行调整。

标签: firebase vue.js google-cloud-firestore


【解决方案1】:

我会稍微调整一下你的 v-if/v-else 逻辑。

<loadingSpinner v-if="loading" />
<div v-else-if="posts.length"></div>
<div v-else>
    <p class="no-results">There are currently no posts</p>
</div>

区别在于v-else-ifposts.length,而不是v-if。这样,就有 3 个不同的状态。

  1. 正在加载,显示微调器。
  2. 未加载,显示帖子。
  3. 没有加载,没有帖子,没有结果。

【讨论】:

    猜你喜欢
    • 2020-01-23
    • 1970-01-01
    • 2013-06-05
    • 2022-06-15
    • 2020-07-24
    • 1970-01-01
    • 2012-08-21
    • 2021-07-17
    相关资源
    最近更新 更多