29

I would like to use the same component for different routes in a Vue.js application.

I currently have something like this:


main.js

const routes = [
    { path: '/route-1', name: 'route-1', component: MyComponent },
    { path: '/route-2', name: 'route-2', component: MyComponent },
    { path: '/route-3', name: 'route-3', component: MyComponent },

]

const router = new VueRouter({
    routes
})

myComponent.vue

<ul>
    <li><router-link to="/route-1">Route 1</router-link></li>
    <li><router-link to="/route-2">Route 2</router-link></li>
    <li><router-link to="/route-3">Route 3</router-link></li>
</ul>

When I type the route manually in the browser, everything is working well, but when I try to navigate between the routes using some of these router-generated-links, nothing happens. The route changes but the content is still the same. Any idea how I can solve this?

Thanks!

1
  • 1
    Well you are using same component so that's why nothing change, in fact only thing that's change is the route. Commented Mar 5, 2017 at 10:59

3 Answers 3

110

This is expected behaviour as Vue is trying to be optimal and reuse existing components. The behaviour you want to achieve used to be solved with a setting called canReuse, but that has been deprecated. The current recommended solution is to set a unique :key property on your <router-view> like so:

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

Check out this JSFiddle example.

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

3 Comments

Works like a charm! I understand the reasons why that's the expected behaviour, but since I have three similar pages with just some content differences, I have to use three different routes to load the right content for each page. That's my very first project and maybe I will find a more elegant solution to achieve the same result. But yeah, thank you! :)
Duuuuuuddddeeeee I was going CRAZY. Glad I found this answer
Solution seems to no longer work with vue 3.3.10 (or higher). Can anyone confirm?
11

You can use watch property, so your component will not waste time to reloading:

index.js You might have something like this

const routes = [
  {
    path: '/users/:id',
    component: Vue.component('user', require('./comp/user.vue').default)
  }
]

user.vue

created(){
  // will fire on component first init
  this.init_component();
},
watch: {
  // will fire on route changes
//'$route.params.id': function(val, oldVal){ // Same
  '$route.path': function(val, oldVal){
    console.log(this.$route.params.id);
    this.init_component();
  }
},
methods: {
  init_component: function(){
    // do anything you need
    this.load_user_data_with_ajax();
  },
}

Comments

2

Just to make a note. If anybody is working with SSR template, things are a bit different. @mzgajner's answer does indeed recreate the component but will not trigger the asyncData again.

For that to happen, modify entry-client.js like this.

OLD:

const activated = matched.filter((c, i) => {
    return diffed || (diffed = (prevMatched[i] !== c))
})

NEW:

const activated = matched.filter((c, i) => {

    /*
        In my case I only needed this for 1 component
    */

    diffed = ((prevMatched[i] !== c) || c.name == 'p-page-property-map')

    return diffed
})

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.