Which VueJS lifecycle hook must Asynchronous HTTP

2019-02-09 11:55发布

I'd like to know how before I render a page, I want to send an async GET request to my server to retrieve data and populate the properties in data. I heard the best way to do this is to call the function that sends this request in one of the three lifecycle hooks Vue js offers that operate before the DOM is rendered. The three are beforeCreate(), created(), beforeMount(). Which one must this request be called in ideally? And why?

4条回答
时光不老,我们不散
2楼-- · 2019-02-09 12:37

The vue-router docs have some advice for patterns to use when retrieving data from a server that is required for component render (see bottom for link).

To determine where to perform the GET request, they first ask if you want to navigate to the route before async GET request is initiated or after

If you want to fetch the data then navigate to the route (before navigation) then the docs suggest performing the async request in the beforeRouteEnter() guard on the incoming component making sure to call next() in beforeRouteEnter() once the async data request has been fulfilled. If you choose this pattern you will want to display some sort of loading indicator as the navigation to the route/rendering of the component will not occur until the data has been fetched.

If you want to navigate to the route then initiate the request (after navigation) then the docs suggest performing the request in the created() hook and using v-if to conditionally show either that the component is loading, an error has occurred, or the view once the data has arrived.

Highly recommend checking out the docs, they have code examples and its well written. https://router.vuejs.org/guide/advanced/data-fetching.html#fetching-before-navigation

查看更多
做自己的国王
3楼-- · 2019-02-09 12:41

It depends.

This depends what you want, for a User Experience. Do you want the route to display immediately, but show a loading spinner on this routes content?

Or do you want to wait until data is fetched, THEN show the route? (which could give the illusion of a laggy application)

If you want to do the first way I mentioned, then you could do it in the created hook of your component.

https://forum.vuejs.org/t/what-is-the-best-hook-to-call-api-to-load-initialisation-data-for-a-component/15167/2

查看更多
霸刀☆藐视天下
4楼-- · 2019-02-09 12:50

Vue's initialization code is executed synchronously.

Technically, any asynchronous code you run in any of those hooks will only respond after all of those hooks end. See 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>

In other words, if you make an Ajax call in beforeCreate, no matter how fast the API responds, the response will only be processed way later, way after the created() has been executed.


What should guide your decision, then?

查看更多
女痞
5楼-- · 2019-02-09 12:56

As mentioned above, the key issue that exists in both Vue and React is, if you make a network request and the data arrives before the component is created, there is no instance to set the data to.

beforeCreated is similar to React's componentWillMount. You generally wouldn't want to execute a network request here because you might get your data back before the component exists. It's like setting this.data = data but there is no component, so this doesn't exist yet.

A better place in React is componentDidMount, but we don't care about that. In Vue, a better place is created because the component has been created already, so this exists.

Here is an example:

<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>
查看更多
登录 后发表回答