![](/img/trans.png)
[英]Vue.js (vuex). Computed property returns undefined when reloading the page. (Hard coded array of objects data in vuex)
[英]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.