Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Precedence in lifecycle hooks with Vue.js and Vue-router

I'm building an app with vue and vue-router. In some routes, I need to check some conditions first, if those conditions are not satisfied, then redirect to another component, so I used the activate hook on the router option of my component, and it works fine. Also, inside that same component, I have the vue created hook to load some data, the thing is that if those conditions that I mentioned before are not met, then I can't load the data in the created hook. What I would expect is that if that condition is not met, and the redirect hook was called, then the created hook wont get triggered, but what is actually happening is that whene that condition is false, then the redirect of the activate hook get calledn and also the created hook from Vue. So, more than a solution for my particular use case, I would like to know the order of execution of the hooks when using vue and vue router together.

like image 608
Yerko Palma Avatar asked Apr 04 '16 14:04

Yerko Palma


2 Answers

For Vue 2.0:

  1. beforeCreate
  2. created
  3. beforeMount
  4. mounted
  5. beforeUpdate
  6. updated
  7. beforeDestroy
  8. destroyed

Now when using vue-router 2.0, the data fetching can be done at two places, as per their doc:

Fetching After Navigation: perform the navigation first, and fetch data in the incoming component's lifecycle hook. Display a loading state while data is being fetched.

Fetching Before Navigation: Fetch data before navigation in the route enter guard, and perform the navigation after data has been fetched.

For your case, you can write you data fetching logic in a function and call it inside the "created" hook of the component lifecylce. If at all the data changes with the route, then write a watcher on the $route object, which will trigger your data fetching function.

As the data hook of vue-router 0.7 is deprecated and instead the $route object has been made reactive. Read more here.

like image 199
Deepak Avatar answered Nov 16 '22 09:11

Deepak


Maybe you are interested in In-Component Guards (additional hooks available in components loaded using Vue Router)

const Foo = {
  template: `...`,
  beforeRouteEnter (to, from, next) {
    // called before the route that renders this component is confirmed.
    // does NOT have access to `this` component instance,
    // because it has not been created yet when this guard is called!
  },
  beforeRouteUpdate (to, from, next) {
    // called when the route that renders this component has changed,
    // but this component is reused in the new route.
    // For example, for a route with dynamic params `/foo/:id`, when we
    // navigate between `/foo/1` and `/foo/2`, the same `Foo` component instance
    // will be reused, and this hook will be called when that happens.
    // has access to `this` component instance.
  },
  beforeRouteLeave (to, from, next) {
    // called when the route that renders this component is about to
    // be navigated away from.
    // has access to `this` component instance.
  }
}

https://router.vuejs.org/guide/advanced/navigation-guards.html#in-component-guards

If you use Vue + Vue Router and you are at RouteA and navigates from it to RouteB and each route/component register for something (e.g. receiving data supported by root) on "created" and unregister on "beforeDestroy" but when you leave RouteA its "beforeDestroy" is called after RouteB "created" so you have nothing registered! I have tested it and VUE 1 had correct order. It must be changed somewhere in VUE 2 + VUE Router 2.

Correct/expected hooks order in VUE 1 when going from RouteA to RouteB:

  • RouteA beforeDestroy
  • RouteB created

Incorrect/unexpected hooks order in VUE 2 when going from RouteA to RouteB:

  • RouteB created
  • RouteA beforeDestroy

Solution is to use "created" + "beforeRouteLeave" for VUE 2 + VUE Router 2.

like image 40
mikep Avatar answered Nov 16 '22 09:11

mikep