Reputation: 565
I'm currently working on a site based on Vue and using Vue Router for routing. My way to handle scroll behavior to anchor links is the following:
const router = new VueRouter({
routes,
scrollBehavior (to) {
if (to.hash) {
return {
selector: to.hash,
offset: { x: 0, y: 140 }
}
}
return { x: 0, y: 0 }
}
})
And my links are built in the following way:
<router-link class="insurance-link d-block" to="#hogar">
<img class="insurance-logo img-fluid" src="@/assets/home-icon.svg">
Hogar
</router-link>
If I click on the link for the first time it scrolls to the anchor position fine, but if I scroll back to the top and click on it for the second time it won't scroll back to that position again. If I click on another anchor link and then click on the previous one everything works fine. Any ideas on what might be happening?
Upvotes: 1
Views: 5370
Reputation: 180
Inspired by Owl's answer, this should work out of the box width vue-router 4.4.x
const router = createRouter({/*...*/});
router.beforeEach((to, from, next) => {
if(to.hash){
document.querySelector(to.hash)?.scrollIntoView()
}
next()
})
Upvotes: 1
Reputation: 565
Given I had limited time (and will, to be honest) to keep on trying solutions I opted to go with vue-anchor-router-link (https://github.com/mperator/vue-anchor-router-link), which worked like a charm. Thank you so much to everyone, your answers helped me understand better the way Vue and Vue Router handle anchor links.
Upvotes: -1
Reputation: 6853
The easiest fix is to use <a>
instead
<a class="insurance-link d-block" href="#hogar">
<img class="insurance-logo img-fluid" src="@/assets/home-icon.svg">
Hogar
</a>
If you want to use <router-link>
and make it work on the 2nd time you click on the router-link, you need to add custom onclick handler like this:
<router-link class="insurance-link d-block" to="#hogar" @click.native="scrollToId('hogar')">
<img class="insurance-logo img-fluid" src="@/assets/home-icon.svg">
Hogar
</router-link>
and add to your vue methods:
methods: {
scrollToId(id) {
document.getElementById(id).scrollIntoView();
}
}
Upvotes: 2
Reputation: 7623
I believe this behavior is due to Vue preventing the click event propagation, and when you're already at the clicked hash, the router considers it a non-change so ignores it. Vue docs state:
In HTML5 history mode, router-link will intercept the click event so that the browser doesn't try to reload the page.
Using the router-link
default slot is one way to take more control. This seems to provide a workaround:
<router-link to="#hogar" v-slot="{ href }">
<a :href="href">Hogar</a>
</router-link>
Upvotes: 0