Reputation: 413
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!
Upvotes: 28
Views: 28952
Reputation: 340
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();
},
}
Upvotes: 11
Reputation: 10477
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
})
Upvotes: 2
Reputation: 2338
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.
Upvotes: 109