2016-06-09 98 views
6

我有单个页面应用程序需要验证。当用户通过身份验证后,访问一些页面或点击浏览器中的重新加载按钮,它会请求提供auth数据的api。然后,我有这样的错误:Vuejs在渲染数据之前同步请求

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

这个错误造成的,因为VUE呈现权威性数据而到API请求还没说完呢。

是否有可能使vue等待请求api,直到完成第一次vue渲染认证数据

更清楚地发生了什么。下面是代码:

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

如你所说的问题是,您尝试访问的对象不存在,而且由于错误的,Vue公司不能在未来打勾渲染。解决方案是使用简单的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已经被渲染时调用ready,并且您希望在该事件之前使用该代码。喜欢['created'](http://vuejs.org/guide/instance。html#Lifecycle-Diagram)hook –

+0

如果我在main.js中调用authService,那该怎么办?例如: '''auth.getUser(null,(response)=> { router.start(App,'#app') })''' 然后在App.vue中只使用以下方法接收auth数据:'' this.authData = auth.user' 我只是试试这个,像预期的那样工作。但我不确定这是否是好解决方案 – antoniputra

+0

,因为如果我使用您提供的解决方案。它会在每个routerComponent中有许多v-if =“dataReady”。 – antoniputra

2

你可以只阻止Vue公司的努力访问对象属性,像这样:

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

你甚至可以更改为null在某些情况下Loading...消息。

1

你可以启用该选项waitForData使用data transition hook

<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/en/pipeline/data.html现在是404 – chovy