我想知道在呈现页面之前,我想向服务器发送异步GET请求以检索数据并填充数据中的属性。我听说最好的方法是调用在三个生命周期钩子之一中发送此请求的函数,Vue js提供在呈现DOM之前运行。这三个是beforeCreate()
,created()
,beforeMount()
。理想情况下,哪个请求必须被调用?为什么?
答案 0 :(得分:17)
Vue的初始化代码是同步执行的。
从技术上讲,您在任何这些挂钩中运行的任何异步代码只会在所有挂钩结束后响应。见demo:
new Vue({
el: '#app',
beforeCreate() {
setTimeout(() => { console.log('fastest asynchronous code ever') }, 0);
console.log('beforeCreate hook done');
},
created() {
console.log('created hook done');
},
beforeMount() {
console.log('beforeMount hook done');
},
mounted() {
console.log('mounted hook done');
}
})
<script src="https://unpkg.com/vue/dist/vue.min.js"></script>
<div id="app">
Check the console.
</div>
换句话说,如果您在beforeCreate
中进行Ajax调用,无论API响应的速度有多快,响应都只会在执行created()
之后的方式处理。 / p>
那么应该指导你的决定呢?
beforeCreate()
data
?
created()
之后生成的任何内容吗?
beforeMount()
created()
无法提供的任何信息,可以在beforeMount()
other than the compiled this.$options.render
render function处找到(请参阅source as well),因此这个案例必须真的是罕见的情况。答案 1 :(得分:2)
vue-router文档为从组件检索所需的服务器中检索数据时使用的模式提供了一些建议(请参阅底部的链接)。
要确定在哪里执行GET请求,他们首先会问您是要导航到之前发起GET请求还是之后
如果您要获取数据,然后导航到路线(在导航之前 ),则文档建议在beforeRouteEnter()
防护中对传入的组件执行异步请求,确保调用完成异步数据请求后,next()
中的beforeRouteEnter()
。如果选择此模式,您将要显示某种加载指示符,因为在获取数据之前,将不会导航到组件的路线/渲染。
如果您想导航至路线,然后发起请求(导航后 ),则文档建议在created()
钩中执行请求,并使用v-if
有条件地执行显示该组件正在加载,发生错误或显示数据到达后的视图。
强烈建议您查看文档,这些文档包含代码示例且编写得井井有条。 https://router.vuejs.org/guide/advanced/data-fetching.html#fetching-before-navigation
答案 2 :(得分:1)
取决于。
这取决于您想要的用户体验。您是否希望路线立即显示,但在此路线内容上显示加载微调器?
或者你想等到获取数据,然后显示路线? (这可能会给人一种迟滞的错觉)
如果您想按照我提到的第一种方式进行操作,那么您可以在组件的创建钩子中执行此操作。
答案 3 :(得分:0)
如上所述,Vue和React中都存在的关键问题是,如果您发出网络请求,并且数据在创建组件之前到达,则没有实例将该数据设置为
。 beforeCreated
与React的componentWillMount
类似。通常,您不想在这里执行网络请求,因为您可能会在组件存在之前取回数据。就像设置this.data = data
一样,但没有任何组件,因此this
尚不存在。
在React中更好的地方是componentDidMount
,但我们对此并不在意。在Vue中,created
是一个更好的地方,因为该组件已经创建,因此this
存在。
这里是一个例子:
<template>
<div>
<span v-if="error">{{ error }}</span><br>
I like:<br>
{{ data }}
</div>
</template>
<script>
export default {
data() {
return {
data: '',
error: undefined,
}
},
async created() {
try {
const response = await axios.get('/endpoint/stuff')
this.data = response
} catch (err) {
this.error = err
}
},
}
</script>