J'ai une application d'une seule page qui nécessite une authentification. Lorsque l'utilisateur a été authentifié, visitez certaines pages ou appuyez sur le bouton de rechargement dans le navigateur, il demandera une API qui fournira leurs données d'authentification. alors j'ai une erreur comme celle-ci:
[Vue warn]: Error when evaluating expression "auth.name": TypeError: Cannot read property 'name' of null (found in component: <navbar>)
Cette erreur est due au fait que vue render données d'authentification alors que la demande à l'API n'est pas encore terminée.
Est-il possible de faire vue attendre l'api de la requête jusqu'à la fin en premier, avant vue render données d'authentification?
juste plus clairement ce qui se passe ici. Voici le code:
// main.js
import Vue from 'vue'
import App from './App.vue' // root vue
import store from './vuex/store' // vuex
import router from './router' // my router map
sync(store, router)
router.start(App, '#app')
// end main.js
// App.vue
<template>
<main>
<div class="wrapper">
<router-view></router-view>
</div>
</main>
</template>
<script>
import authService from './services/auth' // import authservice
ready () {
// here is code that should be done first before vue render all authData
auth.getUser((response) => {
self.authData = response
})
},
data () {
return {
authData: null // default is null until the api finish the process
}
}
</script>
// end App.vue
// SomeRouterComponents.vue
<template>
<!-- some content -->
<div>
// always got error: cannot read property 'name' of null
// here I expect to render this after api has been resolved
{{ $root.authData.name }}
</div>
<!-- some content -->
</template>
Le problème, comme vous l'avez dit, est que vous essayez d'accéder à un objet qui n'est pas présent, et à cause de l'erreur, Vue ne peut pas le restituer dans le prochain tick. La solution est d'utiliser un simple v-if
pour vérifier si les données sont chargées, cela ne fonctionne que pour les données réactives.
composant racine
import auth from './services/auth' // import authservice
ready () {
// here is code that should be done first before vue render all authData
auth.getUser((response) => {
self.authData = response
self.dataReady = true
})
},
data () {
return {
authData: null, // default is null until the api finish the process
dataReady: false
}
}
autreComposant
<div v-if="dataReady">
// note that if you use v-show you will get the same error
{{ $root.authData.name }}
</div>
<div v-if="!dataReady">
// or some other loading effect
Loading...
</div>
J'ai utilisé v-if="!dataReady"
au lieu de v-else
car il sera obsolète dans Vue 2.0
Vous pouvez simplement empêcher Vue d'essayer d'accéder à la propriété de l'objet, comme ceci:
{{ $root.authData ? $root.authData.name : null }}
Vous pouvez même changer null
pour un Loading...
message dans certains cas.
Vous pouvez utiliser le data transition hook
avec l'option waitForData
activée:
<script>
import authService from './services/auth'
export default {
route: {
waitForData: true, // wait until data is loaded
data (transition) {
authService.getUser((response) => {
transition.next({ authData: response }) // set data
})
}
},
data () {
return {
authData: null
}
}
}
</script>
De plus, si vous ne souhaitez pas utiliser cette option, vous pouvez vérifier si les données sont chargées en utilisant le $loadingRouteData
propriété.
Plus de détails ici: http://router.vuejs.org/en/pipeline/data.html