Vue-Router, router.onReady() - vue.js

I am new to vue. I would like to understand when exactly onReady() function will be fired. Vue Router docs explains this below
This method queues a callback to be called when the router has completed the initial navigation, which means it has resolved all async enter hooks and async components that are associated with the initial route.
However, I am not quite understand couple of things here,
What does initial navigation mean?
What does it mean by async enter hooks?
Please help me on this

Just in my opition, not very clear of it, hope there will be more authoritative answer.
1.When vue-router instance initialization finished.(Like when page refreshed, vue-router need create new instance.)
2.async hooks means routes that specific a async component.(When pack with webpack , it will split code into a chunk.)
{
path: '/payment',
component: () => import('#/view/payment'),
},

Related

Vue Lifecycle — which happens before page renders?

Using Vue 2, I want to run a check before any page elements are rendered, to determine whether the user is signed in and if so, redirect them to another page.
Looking at the Vue Lifecycle, it's my understanding that beforeMount is first in this cycle. However, the page still appears for half a second before redirecting (in my case, to Dashboard)
beforeMount() {
firebase.auth().onAuthStateChanged((user) => {
if (user) {
this.$router.push({ name: 'Dashboard'})
}
});
}
I've tried other Lifecycle options and none of the others work either. What am I doing wrong?
Looking at the Vue's lifecycle diagram:
beforeCreate and created hooks are earlier than beforeMount. You should use either one of them.
You have to use Guard for this. you have to check auth before going to route on router.js file. you can use beforeEnter into your route path.
read more about that here: https://router.vuejs.org/guide/advanced/navigation-guards.html#per-route-guard

Vue2 $router.replace() does not call mounted hook

I have Nuxt Vue 2 app. There is a redirect in the mounted hook to the same route. The only difference in this route is query string. It looks like
mounted() {
...
if( !isTokenOwner ) {
const result = await this.$api.campaignNewShare.copyNewShare(this.newShareToken);
localStorage.setItem(result.data.token, new Date().getTime());
this.$router.replace({'name': 'campaigns-new', 'query': {token: result.data.token}});
this.loading = false;
return;
}
}
It seems that Vue stays on the same page and only replace the url query string parameter. But I need to redirect to the new location with whole new lifecycle.
Can somebody tell me what really happened there after the replace() call? Why it does not trigger the real redirect? Thnaks.
Ok so as documentation says
One thing to note when using routes with params is that when the user
navigates from /user/foo to /user/bar, the same component instance
will be reused. Since both routes render the same component, this is
more efficient than destroying the old instance and then creating a
new one. However, this also means that the lifecycle hooks of the
component will not be called.

Vuejs not triggering mounted after user pressed back on his browser

On my vuejs application there is a dashboard, where the user can click a button that send him to /room (router.push("/room");).
When the user arrive on the page, the "mounted" function is triggered and a simple console.log is emited. That works.
mounted() {
console.log("room mounted");
}
If the user press the "back" button of his browser and go back to the dashboard, he can click the button again to join the room, except this time, the "mounted" function is not triggered.
Is there a way to make this works ?
Thank you.
In response to a part of your response to the answer below,
what I'm looking for is when I click again on the button that trigger
the router.push("/room"), because when I'm redirected, mounted nor
updated` are called.
To solve your problem, you can watch the $route object, by doing
watch: {
'$route' () {
// this will be called any time the route changes
}
},
This is expected behavior in Vue Router according to this issue on the Vue Router GitHub repo:
This is expected behaviour, Vue re-uses components where possible.
You can use the beforeRouteUpdatehook to react to a route switch that
uses the same component.
Navigating "back" to an already-mounted component won't trigger a subsequent mounting of the component. To see which lifecycle hooks are triggered on Route Update, you can look at this blog post (scroll down to the Lifecycle Hooks diagram).
The situation you're running into is the "Client Update" column, where mounted is not called, but update is. In general, I tend to utilize parallel code in both beforeRouteEnter and beforeRouteUpdate. Sadly, it's a bit repetitive.

Load async data into the vuex store when Nuxt app loads

I am trialling a project in Nuxt. Liking it so far except I am a little confused as to how to load data from an external async service so that it is available in Vuex from the very first route.
I have tried adding middleware on the default layout to dispatch the store action but I do not see the service being called straight away. Only when I navigate deeper into the routes do I see the action dispatched.
I did something similar in a standard Vue project and added the created method to the App.vue.
Is there a similar way in Nuxt?
What you need is called a fetch.
The fetch method, if set, is called every time before loading the component (only for page components). It will be called server-side once (on the first request to the Nuxt app) and client-side when navigating to further routes.
Warning: You don't have access of the component instance through this inside fetch because it is called before initiating the component.
async fetch({ store }) {
await store.dispatch('your-action')
}
If you need parameter:
async fetch({ store, params }) {
await store.dispatch('your-action', params.id)
}
I gave an example of id. The name of the parameter depends on the name of your page.
_id => params.id
_slug => parmas.slug
...

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.
For Vue 2.0:
beforeCreate
created
beforeMount
mounted
beforeUpdate
updated
beforeDestroy
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.
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.
Why not add console logs to each and see for yourself?
As far as I can tell without testing:
canReuse
canActivate
-- now the component instance is being created:
created
beforeCompile
compiled
-- (not sure wheither ready or activate comes first, but i guess ready)
ready
activate
data
For your particular case, the data fetching should happen in the data hook - that's what it's for, after all.