2016-06-09 23 views
6

Ich habe Single-Seite-Anwendung, die Authentifizierung erfordert. Wenn der Benutzer authentifiziert wurde, besuchen Sie einige Seiten oder klicken Sie auf die Schaltfläche zum erneuten Laden im Browser, um eine API anzufordern, die ihre Authentifizierungsdaten zur Verfügung stellt. dann habe ich einen Fehler wie folgt aus:Vuejs synchron vor dem Rendern Daten anfordern

[Vue warn]: Error when evaluating expression "auth.name": TypeError: Cannot read property 'name' of null (found in component: <navbar>)

Dieser Fehler wird verursacht, weil vue Auth Daten machen während die Anforderung an api noch nicht beendet haben.

Ist es möglich, vue warten die Anfrage api bis zum Abschluss zuerst, bevor vue render auth Daten?

nur deutlicher was hier vor sich geht. Hier ist der 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> 
+0

Sie sollten Ihren Code schreiben. Ich glaube nicht, dass notwendig ist synchron zu gehen –

+0

@YerkoPalma Ich benutze Vue-Router und Vuex. Zur Zeit stelle ich Code (für eine Anfrage api) in App.vue bereit() – antoniputra

+0

@YerkoPalma Mein Code ist wie allgemeines Einseiten-App-Projekt, bis ich auf dieses Problem stoße. – antoniputra

Antwort

9

Das Problem, wie Sie gesagt, dass Sie versuchen, ein Objekt zuzugreifen, die nicht vorhanden ist, und aufgrund des Fehlers, Vue kann es in dem nächsten Tick nicht machen. Die Lösung besteht darin, eine einfache v-if zu verwenden, um zu überprüfen, ob die Daten geladen sind, dies funktioniert nur für reaktive Daten.

Wurzelkomponente

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 
    } 
    } 

andere Komponente

<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> 

I v-if="!dataReady" statt v-else verwendet, weil es

+0

Versuchen Sie auch, einen anderen Zyklus-Hook anstelle von 'ready' zu verwenden, da ready aufgerufen wird, wenn das DOM gerendert wurde, und Sie möchten diesen Code vor diesem Ereignis haben. Bevorzugt ['erstellt'] (http://vuejs.org/guide/instance.html # Lifecycle-Diagramm) hook –

+0

wie wäre es, wenn ich den authService in main.js aufrufen. wie: '' 'auth.getUser (null, (Antwort) => { router.start (App, '#app') })' '' dann in App.vue erhalten Sie nur die Auth-Daten mit: ' this.authData = auth.user' Ich versuche es einfach und arbeite wie erwartet. aber ich bin mir nicht sicher, ob das eine gute Lösung ist – antoniputra

+0

, denn wenn ich die Lösung, die Sie gaben. es wird viele v-if = "dataReady" in jeder routerComponent haben. – antoniputra

2

in Vue 2.0 veraltet werden Sie könnten Vue nur verhindern, versuchen um auf die Objekteigenschaft zuzugreifen , Wie folgt aus:

{{ $root.authData ? $root.authData.name : null }} 

Sie könnten sogar null in einigen Fällen für eine Loading... Nachricht ändern.

1

Sie konnten die data transition hook mit der aktivierten Option waitForData verwenden:

<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> 

Auch wenn Sie diese Option nicht verwenden möchten, können Sie überprüfen, ob die Daten unter Verwendung der $loadingRouteData Eigenschaft geladen wird.

Weitere Details hier: http://router.vuejs.org/en/pipeline/data.html

+0

https://router.vuejs.org/de/pipeline/data.html ist jetzt ein 404 – chovy