19

Please, look the flux below, it's shows my problem. I'm using vue-router with this.$router.push to browsing on pages. I'm starting on PageA.

  • PageA -> PageB ( mounted() of PageB is called)

  • PageB -> PageA (returning to PageA)

  • PageA -> PageB (mounted() of PageB is not called)

It sounds that page (.vue component) is not closed and mainted on cache or other thing. I must use the mounted() method every time that page is open and maybe close the page and clean from cache. How I can solve it?

4 Answers 4

9

Vue 3

For those that ended up here like me looking at why I'm not getting unmounted called on a component inside a page, when route changes, here's some guidance:

Let's say you have Page A that uses Component A in it, and Page B that does not use Component A.

When you open Page A for the first time, Component A will have, as expected, mounted method called.

However, when you navigate to Page B, Vue3 won't un-mount or destroy Component A, rather it will deactivate it, and deactivated method will be called instead of unmounted.

Once you navigate back to Page A, Component A will be reactivated and method activated will be called instead of mounted.

Sign up to request clarification or add additional context in comments.

2 Comments

This feature was added on Vue3?
@Augusto tested in my current project. This is the first project I use Vue 3 so it's pretty new to me as well how their component life cycle works now.
7

vue will re-use components were possible, this is expected.
Normally you would watch for route changes and update your component state accordingly.

To react to route changes you can use beforeRouteUpdate():

const Example = Vue.extend({
  template: `
  	<div>
  		<p>This changes: '{{param}}'</p>
    </div>`,
  data(){
    return {
      param: this.$route.params.param
    };
  },
  beforeRouteUpdate(to, from, next) {
    this.param = to.params.param;
    next();
  }
});

const router = new VueRouter({
  routes: [
    {
      path: '/:param', component: Example,
    }
  ]
})
const app = new Vue({ router }).$mount('#app')
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>

<div id="app">
  <router-link to="/foo">foo</router-link><br>
  <router-link to="/bar">bar</router-link><br>
  <router-view></router-view>
</div>

Alternatively you can also watch the route and update the state accordingly:

Vue.extend({
  watch: {
    '$route'() {
      // TODO: react to navigation event.
      // params cotains the current route parameters
      console.log(this.$route.params);
    }
  },
  // ....
});

The vue-router documentation has a few great examples for this: Data Fetching - Vue Router

If you still want to use mounted(), you can do so by giving your router-view a key that will change when the route changes, e.g.:

<router-view :key="$route.fullPath"></router-view>

This will force the component to be re-created every time, so it does have a performance penalty - i would recommend using the route hooks described above, if possible.

7 Comments

Your explanation was productive but your solution not solved my problem. 1. I followed your code tips but not worked to me. 2. My project is very big and I can't edit the <router-view> because very people works them. I need a solution that can be implemented on the specific component.
@Augusto what kind of logic do you have in your mount() hook? could you post it? what are the routes, how do they change? - There is unfortunately no way for a component to unmount & remount itself - mount() will only be called once - the only way you can force a component to be re-mounted is to give it a key - which in this case unfortunately has to be on the router-view if your component gets rendered from a route
In my mount() I must read state to get pre-selected or reset form's data. Imagine the follow behavior, the user open form page and edit it, but when him closes the page the form must be reseted, but, like vuejs re-use component the form is re-used and the data is not reseted.
Reading others questions, the key and watchers sounds be a solution but I don't know use them.
then you could move the code from your mount() hook into a method and call that one from mount() and beforeRouteUpdate(). If you also want to clear the data of your component you can additionally use Object.assign(this.$data, this.$options.data()) in your beforeRouteUpdate hook
|
1

For those who are using the Composition API for Vue 3:

This use case is for fetching data from an API upon component mount and other dependencies. Instead of watch, you need to use watchEffect to automatically track the dependencies and perform side effects on mount.

watchEffect(fetchData);

watch(dependencies, callback) will trigger on first visit to the route. But if you go to another page, then come back to it, it won't trigger again because it does not count the initial state as an update. Also, the dependencies technically did not change from the time it was mounted.

Additional Notes:

  • If you are coming from React, watch is not exactly equivalent to useEffect. watchEffect is more similar to it.

  • For comparison, this code should have the same results as the watchEffect one. But watchEffect is more concise.

onMounted(fetchData);
watch([dependency 1, dependency 2, ...], fetchData);

Comments

1

Ionic Framework Vue3

Also for those that ended up here like me looking at why the hooks dont work!, refer to the ionic docs lifecycle changes on ion-router-outlet.

Hope to save lots of hours that cost for me.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.