0

I implemented the code from this post, enabling the scroll to anchor while navigating using the router.

But I noticed that on a refresh or manual navigation (by manipulating the URL), the page does not scroll to anchor as expected.

I can add this code to all pages, and it is going to work:

mounted() {
    console.log('Location:', location.hash); //returns '#options'
    console.log('Route:', this.$route.hash); //returns '#options'

    if (location.hash)
        this.$nextTick().then(() => this.$scrollTo(location.hash, 700));
}

Is there any global way to set this code, without having to set the code in every page?

I've tried to set that on the App.vue file, the location.hash prop returns the correct hash, but this.$scrollTo() says that it can't find any object with that ID.

Nicke Manarin
  • 2,294
  • 1
  • 24
  • 59

1 Answers1

0

I simply used a vue-router navigation guard:

const router = new VueRouter({
    mode: "history",
    base: process.env.BASE_URL,
    routes,

    scrollBehavior (to, from, savedPosition) {
        if (to.hash) {
            this.app.$scrollTo(to.hash, 700);
            return { selector: to.hash }
        } else if (savedPosition) {
            return savedPosition;
        } else {
            //When the route changes, the page should scroll back to the top.
            this.app.$scrollTo('#app', 700);
            return { x: 0, y: 0 }
        }
    }
});

router.afterEach((to, from) => {
    if (to.hash && to.path != from.path)
        Vue.nextTick().then(() => VueScrollTo.scrollTo(to.hash, 700));
});

Unrelated to the question, but related to the navigation with hashes:

If you are publishing your website in GitHub Pages, you'll need to add these next two parts.

Add a 404.html static page, to redirect the navigation back to the root page, but passing a few parameters in the sessionStorage:

<script>
    const segment = 1;  
    //Gets the relative path and the hash of the URL.  
    sessionStorage.redirect = '/' + location.pathname.slice(1).split('/').slice(segment).join('/');  
    sessionStorage.hash = location.hash;  

    //Forces the navigation back to the main page, since it's the only entry point that works.
    location.replace(location.pathname.split('/').slice(0, 1 + segment).join('/'));
</script>

Alter your main.js page to expect the redirect parameters:

new Vue({
    router,
    i18n,
    render: (h) => h(App),
    created() {
        //If a redirect exists, tell the router.
        if (sessionStorage.redirect) {
            const redirect = sessionStorage.redirect;
            const hash = sessionStorage.hash;
            delete sessionStorage.redirect;
            delete sessionStorage.hash;

            this.$router.push(redirect + hash);
        }
    }
}).$mount("#app");
Nicke Manarin
  • 2,294
  • 1
  • 24
  • 59