2016-06-09 10 views
6

У меня одностраничное приложение, требующее аутентификации. Когда пользователь был аутентифицирован, затем зайдите на некоторые страницы или нажмите кнопку перезагрузки в браузере, он попросит api предоставить свои данные аутентификации. то у меня есть ошибка, как это:Vuejs синхронно запрашивает данные рендера

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

Эта ошибка вызвана тем, что вю визуализации аутентификации данных в то время как запрос API еще не закончена.

Можно сделать vue ждать запроса api до окончания первого, прежде чем vue render auth data?

как раз более четко что происходит здесь. Вот код:

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

Вы должны опубликовать свой код. Я не думаю, что нужно синхронно идти –

+0

@YerkoPalma Я использую vue-router и vuex. в настоящее время я помещаю код (для запроса api) в App.vue в ready() – antoniputra

+0

@YerkoPalma. Мой код похож на общий проект приложения с одной страницей, пока я не встречу эту проблему. – antoniputra

ответ

9

Проблема, как вы сказали, что вы пытаетесь получить доступ к объекту, который не присутствует, и из-за ошибки, Вю не может сделать это в следующем такте. Решение состоит в том, чтобы использовать простой v-if, чтобы проверить, загружены ли данные, это работает только для реактивных данных.

корневой компонент

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

otherComponent

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

Я использовал v-if="!dataReady" вместо v-else, потому что он будет устаревшим в Vue 2,0

+0

Кроме того, попробуйте использовать еще один цикл-крючок вместо 'ready', поскольку готовый вызывается при визуализации DOM, и вы хотите этот код перед этим событием. Предпочитают ['created'] (http://vuejs.org/guide/instance.html # Lifecycle-Diagram) hook –

+0

как насчет того, позволю ли я authService в main.js. например: '' 'auth.getUser (null, (response) => { router.start (App, '#app') })' '' , то в App.vue только получить данные auth, используя: ' this.authData = auth.user' Я просто попробовал это и работал, как ожидалось. но я не уверен, что это хорошее решение – antoniputra

+0

, потому что если я использую решение, которое вы дали. он будет иметь много v-if = "dataReady" в каждом маршрутизаторе. – antoniputra

2

Вы можете просто предотвратить Vue от попыток для доступа к объекту , Как это:

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

Можно даже изменить null для Loading... сообщения в некоторых случаях.

1

Вы можете использовать data transition hook с waitForData включенной опцией:

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

Кроме того, если вы не хотите использовать эту опцию, вы можете проверить, если данные загружаются с помощью $loadingRouteData свойства.

Подробнее здесь: http://router.vuejs.org/en/pipeline/data.html

+0

https://router.vuejs.org/ru/pipeline/data.html - это 404 сейчас – chovy