How to handle anchors (bookmarks) with Vue Router?
I haven't found anything in the resources to solve your issue but you could utitlize the $route.hash
in your mounted
hook of the component that holds your <router-view></router-view>
to solve the refresh issue.
<script>
export default {
name: 'app',
mounted: function()
{
// From testing, without a brief timeout, it won't work.
setTimeout(() => this.scrollFix(this.$route.hash), 1);
},
methods: {
scrollFix: function(hashbang)
{
location.hash = hashbang;
}
}
}
</script>
Then to solve the issue of second clicks you could use the native
modifier and bind to your <router-link></router-link>
. It's a fairly manual process but will work.
<router-link to="#scroll" @click.native="scrollFix('#scroll')">Scroll</router-link>
There may also be something you could do with the router's afterEach
method but haven't figured that out yet.
Possible solution which is more resusable IMO:
this.$router.push({ name: 'home' }, undefined, () => { location.href = this.$route.hash })
As the 3rd argument is the abort() function, it may have unwanted side effects though..
If you want to use it globally, add a function to your Router:
pushWithAnchor: function (routeName, toHash) {
const fromHash = Router.history.current.hash
fromHash !== toHash || !fromHash
? Router.push({ name: routeName, hash: toHash })
: Router.push({ name: routeName, hash: fromHash }, undefined, () => { window.location.href = toHash })
}
And use it in components with:
this.$router.options.pushWithAnchor('home', '#fee-calculator-section')
Within a template you could do something like:
<a @click="this.$router.options.pushWithAnchor('home', '#fee-calculator-section')"></a>
Sadly you cant use a scroll offset though
If you're already on the route with the hash, you can just set it to scroll to the target.
(also note scrollBehavior()
method in your router won't get called if you're already on the route you're trying to go to).
export default {
methods: {
anchorHashCheck() {
if (window.location.hash === this.$route.hash) {
const el = document.getElementById(this.$route.hash.slice(1))
if (el) {
window.scrollTo(0, el.offsetTop)
}
}
},
},
mounted() {
this.anchorHashCheck()
},
}
Then add a @click.native
to listen to events on the anchor in your <router-link>
,
<router-link :to="{hash: '#some-link'}" @click.native="anchorHashCheck">
Some link
</router-link>