Javascript Vuejs 在渲染数据之前同步请求
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/37733935/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Vuejs synchronously request before render data
提问by antoniputra
I have single page application that requires authentication. When user was authenticated then visit some pages or hit reload button in browser it will request an api that provide their auth data. then I have an error like this:
我有需要身份验证的单页应用程序。当用户通过身份验证然后访问某些页面或点击浏览器中的重新加载按钮时,它将请求提供其身份验证数据的 api。然后我有一个这样的错误:
[Vue warn]: Error when evaluating expression "auth.name": TypeError: Cannot read property 'name' of null (found in component: <navbar>)
[Vue warn]: Error when evaluating expression "auth.name": TypeError: Cannot read property 'name' of null (found in component: <navbar>)
This error is caused because vue render auth datawhile the request to api have not finished yet.
这个错误是因为 vue 渲染auth 数据而对 api 的请求还没有完成引起的。
Is possible to make vue wait the request api until finish first, before vue render auth data?
在 vue 呈现身份验证数据之前,是否可以让 vue 等待请求 api 直到完成?
just more clearly what going on here. Here is the 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>
回答by Yerko Palma
The problem as you said is that you try to access an object that isn't present, and because of the error, Vue can't render it in the next tick. The solution is to use a simple v-if
to check if the data is loaded, this work only for reactive data.
正如你所说的问题是你试图访问一个不存在的对象,并且由于错误,Vue 无法在下一个滴答中呈现它。解决方案是使用一个简单的方法v-if
来检查数据是否已加载,这仅适用于反应性数据。
root component
根组件
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>
I used v-if="!dataReady"
instead of v-else
because it will be deprecated in Vue 2.0
我使用v-if="!dataReady"
而不是v-else
因为它将在 Vue 2.0 中被弃用
回答by crabbly
You could just prevent Vue from trying to access the object property, like this:
您可以阻止 Vue 尝试访问对象属性,如下所示:
{{ $root.authData ? $root.authData.name : null }}
You could even change null
for a Loading...
message in some cases.
你甚至可以改变null
一个Loading...
在某些情况下的消息。
回答by Pantelis Peslis
You could use the data transition hook
with the waitForData
option enabled:
您可以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>
Also, if you don't want to use that option, you could check if the data is loaded by using the $loadingRouteData
property.
此外,如果您不想使用该选项,您可以使用该$loadingRouteData
属性检查数据是否已加载。
More details here: http://router.vuejs.org/en/pipeline/data.html