Deniz
Deniz

Reputation: 1503

Vue switching between same components in router-view will not mounted/created again

When using same components, like two versions of User.vue which are only different in there data, then when switching between those, there will not be used a created or a mounted lifecycle function in vue.

What i mean:

no changes


But, when i switch to a other component, in my case the Welcome.vue page, and then switching back to to one of my User.vuecomponents, it works as it should. In this case the User.vue component will use its own created function and reloads the user related data from my store.

Example:

how it works


As you can see the component will be re-rendered and loads his related user data like it should.

my User.vue component

<template>
  <div>
    <UserInfo
      :user-name="userName"
      :budget="budget"
    />
    <UserIncExp />
  </div>
</template>

<script>
import UserInfo from '../User/UserInfo.vue';
import UserIncExp from '../User/UserIncExp/_UserIncExp.vue';
export default {
  components: {
    UserInfo,
    UserIncExp
  },
  data() {
    return {
      userName: '',
      budget: ''
    };
  },
  computed: {

  },
  watch: {
    '$route.params.id': id => {
      console.log(id);
      this.loadUserDataFromState();
    }
    // this.userName = this.$store.state.users[this.$attrs.userId].userName;
    // console.log(this.userId);
  },
  created: function() {
    this.loadUserDataFromState();
  },
  methods: {
    loadUserDataFromState() {
      console.log('route changed');
      this.userName = this.$store.state.users[this.$attrs.userId].userName;
      this.budget = this.$store.state.users[this.$attrs.userId].salery;
      console.log(this.userName);
      console.log(this.budget);
    }
  },
};
</script>

<style>
</style>

User.vue fetchs his data from a store.state like this:

  state: {
    users: [
      // {
      //   userName: 'John',
      //   salary: 2000,
      //   leftover: 0,
      //   inc: [],
      //   exp: [],
      //   active: false,
      // }
    ],
    // placeholder: true
  },

The parent is App.vue with a used <router-link> for Users.

<template>
  <div id="app">
    <Navigation />
    <router-view />
  </div>
</template>

<script>
// import { mapState } from 'vuex';
import Navigation from './components/Navigation/_Navigation.vue';
export default {
  components: {
    Navigation
  },
  computed: {}
};
</script>

<style lang="scss">
#app {
  height: 1200px;
  width: 100vw;
  background-color: $dark;
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  color: #ffffff;
  a:hover {
    color: $orange;
  }
  a {
    color: $white;
  }
  *:focus {
    box-shadow: 0 0 0 0.2rem rgba(233, 84, 32, 0) !important;
  }
}
</style>

And finally my router config, if needed for you

import Vue from 'vue';
import VueRouter from 'vue-router';
import Welcome from '../views/Welcome.vue';
import User from '../components/User/_User.vue';

Vue.use(VueRouter);

const routes = [
  {
    path: '/',
    name: 'Welcome',
    component: Welcome
  },
  {
    path: '/user/:userId',
    name: 'User',
    component: User,
    props: true
  }
];

const router = new VueRouter({
  // mode: 'history',
  base: process.env.BASE_URL,
  routes
});

export default router;

Upvotes: 1

Views: 1695

Answers (1)

Shivam Singh
Shivam Singh

Reputation: 1731

You are watching $route.params.id instead of $route.params.userId, as in router config you have added param as /user/:userId

watch: {
  "$route.params.userId": { // <-- here 
    handler () {
      this.loadUserDataFromState();
    },
    immediate: true // will call handler on component mount / create as well, so no need to call fn on mounted again
    }
  },

alternative

beforeRouteUpdate (to, from, next) {
 if (from.name === to.name) { // Call fn only when: route hasn't changed instead just query/params for the route has changed
  this.loadUserDataFromState();
 }
},

Upvotes: 4

Related Questions