4

I'm trying to develop a simple website using vue js and so far it goes well but I'm facing the following Issue:

I'm using a router to change pages, it works, but what I need to do is: Change Page & scroll to a specific anchor.

What I tried already:

Works well: Route to contact page or home

<router-link to="/contact">Contact</router-link>
<router-link to="/">Home</router-link>

Doesn't work:

<router-link :to="{ name: '/', hash: '#technology' }" >Technology</router-link>

The last one works only if I'm on the home page, but whenever I change to Contact Page and try to route to "/#technology" it won't work. It does try routing to "http://example.com/contact/#technology" instead of "http://example.com/#technology".

If I do it like that, it will just scroll to top, but not to the anchor:

<router-link to="/#technology" Technology</router-link>

My Router Code:

const routes = [
    { path: '/', component: Home },
{ path: '/contact', component: Contact }
]

const router = new VueRouter({
     mode: 'history',

     routes,
       scrollBehavior(to, from, savedPosition) {
        if (savedPosition) {
            return savedPosition;

        }

         if (to.hash) {
            return { selector: to.hash };
        }
    return { x: 0, y: 0 }
  },


});

new Vue({
    router,
}).$mount('#app');

And the templates look like this ( I did remove the unnecessary code):

<template id="home">
<div>
Home
<div id="technology"> <!-- IT SHOULD SCROLL TO HERE -->
</div>
</template>

<template id="contact">
<div>
Contact Page
</div>
</template>

2 Answers 2

9

i think you are on the right path.

but maybe you have mistaken the usage of Route name and path.

instead of

<router-link :to="{ name: '/', hash: '#technology' }" >Technology</router-link>

try using path instead of name

<router-link :to="{ path: '/', hash: '#technology' }" >Technology</router-link>
Sign up to request clarification or add additional context in comments.

3 Comments

Thank you, Jacob! True, seems like I really misunderstood the difference between path and name. :)) Thank you! For sure I'm a big step closer to my goal. Now it redirects/routes to the right page/path but doesn't scroll to the anchor. Do you have any idea how to acchieve that?
I just got it work using a vue js scroll-to plugin but maybe there is a way to acchieve the same without the need of a plugin? That's the plugin: github.com/rigor789/vue-scrollto?ref=madewithvuejs.com And what I did was: <router-link :to="{ path: '/', hash: '#technology' }">Technology</router-link> and const Home = { template: '#home', mounted: function(){ if(this.$router.currentRoute['hash']){ Vue.use(VueScrollTo); VueScrollTo.scrollTo(this.$router.currentRoute['hash'], 500); } }}
Oddly this is undocumented in Vue 2 docs: v3.router.vuejs.org/api/#to
0

Using Vue 3 + Vue-Router 4, this worked for me:

function scrollBehavior (to, from, savedPosition) {
  // check that path is different, so this doesn't scroll to top every time
  // a query parameter is changed
  if (to.path !== from.path) {
    if (
      // if this is a push/pop state (forward/back), use the saved position
      savedPosition ||
      (
        // don't change screen position when closing/opening a modal
        to.meta?.savePosition ||
        to.params?.savePosition
      )
    ) {
      return savedPosition;
    }

    // If the url has a #sub-section scroll to there
    if (to.hash) {
      return { el: to.hash, top: 20 };
    }

    // otherwise always scroll to the top of the page
    return new Promise((resolve) => {
      // Resolving a promise is needed for some async routes.
      // Has no negative impact on synchronous routes.
      resolve({ left: 0, top: 0 });
    });
  }
}

The 20 is an offset, if you set it to 0 it will be right on the element with the ID, if you set it to 300 then the element will be visible 300 pixels below the top of the visible area.

Bonus, it works with name, so you don't need to use path.

<RouterLink
  :to="{
    name: 'routeName',
    hash: '#my-hash'
  }"
>
  Link
</RouterLink>

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.