簡體   English   中英

Vue JS 計算屬性未定義(vuex 中的異步 axios 調用)

[英]Vue JS computed property is undefined (async axios call in vuex)

所以問題是所有在存儲中有 axios 調用的計算屬性都運行良好,除了一個特定的。 GetSong.owner 未定義,但問題是數據在網頁上正確顯示。 該錯誤僅在刷新時出現,所以我想它與在存儲中的 axios 調用完成之前加載的 dom 有關。 有任何想法嗎? 這是代碼:

<div>
   <div class="song">
       <div class="song_container">
           <div class="song_info">
               <h1 v-if="getSong" class="song_info-author">{{ getSong.owner.profile[0].name ? getSong.owner.profile[0].name : '' }}</h1>
               <h1 class="song_info-title">{{  getSong.title }} </h1>
               <h1 class="song_info-genre">{{  getSong.genre }} </h1>
           </div>
           <div class="song_playback">
               <app-player></app-player>
           </div>
        <img v-bind:class="{'liked': getLiked}" @click.prevent="likeUnlikeSong" 
       class="song_like" src="../assets/icons/favourite.svg" alt="" srcset="">
       </div>
       <app-comment></app-comment>
   </div>
</div>
</template>

<script>
import Comment from "../components/Comment.vue";
import Player from "../components/Player.vue";
export default {
    components : {
       appComment : Comment,
       appPlayer : Player
   },
   computed: {
       getSong(){
           return this.$store.getters.getSong
       },
       getLiked() {
           return this.$store.getters.getLiked
       },
       getProfile() {
           return this.$store.getters.getProfile
       },
       getImage() {
       return this.$store.getters.getImage
       }
   },
   methods : {
         likeUnlikeSong (){
           if(!this.getLiked){
               this.$store.dispatch('LIKE_SONG',this.$route.params.id)
           } else {
               this.$store.dispatch('UNLIKE_SONG',this.$route.params.id)
           }
       },
   },
   created() {
        this.$store.dispatch('GET_SONG',this.$route.params.id)
        this.$store.dispatch('CHECK_LIKE',this.$route.params.id)

   }

}
</script>

<style lang="scss" scoped>
@import '../scss/components/song';

</style> 

店鋪:


const song = {
    state : {
        song : {},
        songs: [],
        my_songs: [],
        liked: false
    },
    getters : {
        getSong : (state) => {
            return state.song
        },
        getAllSongs: (state) => {
            return state.songs
        },
        getLiked : (state) => {
            return state.liked
        },
        getMySongs : (state) => {
            return state.my_songs
        }
    },
    mutations : {
        setSongOne : (state,song) => {
            state.song = song
        },
        removeSongOne : (state) => {
            state.song = null
        },
        setAllSongs : (state,songsArray) => {
           state.songs = songsArray
        },
        emptyAllSongs: (state) => {
            state.songs = []
        },
        setLike: (state,boolean) => {
            state.liked = boolean
        },
        setMySongs : (state,songs) => {
            songs.forEach((song) => {
                state.my_songs.push(song)
            })
        },
        reset: (state) => {
            state.song = {},
            state.songs = [],
            state.my_songs = [],
            state.liked =  false
        }
    },
    actions : {
        UPLOAD : ({commit}, payload) => {
            return new Promise((resolve,reject) => {
                Axios.post('/song',payload)
                .then((success) => {
                   resolve()
                }).catch((error) => {
                    reject(error)
                })

            })

        },
        GET_SONG: ({commit}, payload) => {
                Axios.get(`/song/${payload}`).then(({data,status}) => {
                    if(status===200){
                        commit('setSongOne',data)
                    } 
                }).catch((error) => {
                })

        },
        GET_MY_SONGS : ({commit,getters}) => {
            if(getters.getMySongs.length == 0){
            return new Promise((resolve,reject) => {
                Axios.get('/song/me').then(({data,status}) => {
                    if(status=== 200) {
                        commit('setMySongs',data)
                        resolve()
                    }
                }).catch((error) => {
                    reject(error)
                })
            })}
        },
        GET_ALL_SONGS: ({commit}) => {
            let songs = []
            return new Promise((resolve,reject) => {
                Axios.get('/song').then(({data,status}) => {
                    if(status===200) {
                        songs.push(data)
                        commit('setAllSongs',songs)
                        resolve()
                    }
                }).catch((error) => {
                    reject(error)
                })
            })

        },
        EMPTY_ALL_SONGS: ({commit}) => {
            commit('emptyAllSongs')
        },
        LIKE_SONG : ({commit},payload) => {
             return new Promise((resolve,reject) => {
                Axios.post(`/song/${payload}/like`).then(({status}) => {
                    if(status===200) {
                        commit('setLike',true)
                        resolve()
                    } 
                }).catch((error) => {
                    reject(error)
                })
             })          
        },
        UNLIKE_SONG : ({commit},payload) => {
            return new Promise((resolve,reject) => {
               Axios.post(`/song/${payload}/unlike`).then(({status}) => {
                   if(status===200) {
                       commit('setLike',false)
                       resolve()
                   }
               }).catch((error) => {
                reject(error)
            })
            })          
       },
        CHECK_LIKE: ({commit},payload) => {
            return new Promise((resolve,reject) => {
                Axios.get(`/song/${payload}/check_like`).then(({status,data}) => {
                    if(status===200) {
                        commit('setLike',data.liked)
                        resolve()
                    } 
                }).catch((error) => {
                    reject(error)
                })
            })
        }
    }
}

export default song

正如你所說,它是在數據加載之前渲染的。

問題是您將商店 state 默認為song: {} ,所以v-if="getSong"總是正確的。

一個快速的解決方法是v-if="getSong.owner" 就我個人而言,我不會那樣修復它,我會將其更改為song: null並在模板上方處理丟失的歌曲。 最終,您需要決定在加載數據時要渲染什么。 在本地這可能需要幾毫秒,但您應該考慮在生產中可能需要多長時間以及您希望用戶看到什么。

在不相關的說明中,您不應該將 axios 調用包裝在承諾中。 Axios 無論如何都會返回承諾,所以你應該只返回那些。 例如:

UPLOAD ({commit}, payload) {
  return Axios.post('/song', payload)
})

更新:

created的鈎子將在渲染發生之前運行,但您正在發出異步請求,並且在繼續渲染之前它不會等待這些請求完成。

在它首先呈現商店時,state 仍將包含您的默認值。 在大多數地方,您的模板處理這些默認值的方式不會導致錯誤,除了getSong.owner.profile部分。 getSong將是一個空的 object,因此getSong.owner將是undefined ,導致嘗試訪問其profile屬性時出錯。

請注意,僅僅因為其他值沒有導致錯誤並不一定意味着它們“正常”工作。 在加載實際值時,用戶將看到部分填充的 UI。 這在完成的應用程序中不太可能是需要的。

當實際值加載時,它將再次呈現,這次沒有錯誤。 不需要setTimeout ,您只需要編寫模板來處理丟失的數據。

如前所述,一種方法是設置song: null並將v-if="getSong"模板的上方,這樣就不會嘗試使用getSong

好的,所以我解決了這個問題。 對於所有遇到同樣問題並使用 express 和 mongoose 的人。 似乎 mongoose 導致了這個問題,因為我在 1 個呼叫中有 2 個填充。 我更改了填充發生的順序,並且錯誤以某種方式消失了。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM