ChatGPT解决这个技术问题 Extra ChatGPT

Vue.js scroll to top of page for same route

I can set scrolling behaviour to Vue.js Router like this:

const router = new Router({
    mode: 'history',
    routes: [
        {
            path: '/',
            name: 'index',
            component: Main
        },
        {
            path: '/some-path',
            name: 'some-path',
            component: SomePath
        }
    ],
    scrollBehavior() {
        return {x: 0, y: 0}
    }
})

This works perfectly when you click on the link with some page which is not current. When I click on the link which is already rendered, i.e. in the footer, nothing happens. Vue Router assumes there is no state transition. What is the preferred way to scroll up in this case?


L
Lee Goddard

You can't do this through vue-router, but you can add a scroll-to-top method to every router-link.

Just create a method like this:

methods: { 
  scrollToTop() {
    window.scrollTo(0,0);
  }
}

Add it to the link:

<router-link @click.native="$scrollToTop">

If you want to use it outside of your footer too, it's better to add it to the Vue prototype

Vue.prototype.$scrollToTop = () => window.scrollTo(0,0)

It's not a 100% solution but it's the simplest one


I was thinking about similar solution. Thanks anyway! :-)
window.scrollTo(0,0); doesnt work at all in my viewJs app, even in console
You should scrolled the scrollable component, typically not even #app but something like #app-content, depends on your app's layout.
This is definitely the best solution. I wanted to do the same thing but animated and the problem is that this one triggers all the time, not just when it's the current route. I really wish there was an event or a callback especially for when you click the current route.
When using the component method you'd leave out the global method signifier '$' and simply write: <router-link @click.native="scrollToTop">
L
Lee Goddard

I couldn't get any of the above solutions working, and it was really frustrating.

What ended up working for me was the below:

    const router = new Router({
        mode: 'history',
        routes: [...],
        scrollBehavior() {
            document.getElementById('app').scrollIntoView({ behavior: 'smooth' });
        }
    })

I mount my VueJs app to #app so I can be certain it is present and is available for selection.


This was really helpful for me, I was having trouble using scrollTo(0,0) within nested Vue routes
this guy was sent by God Himself! 🙌
I too was having trouble using the accepted answer. This worked like a charm. Thanks.
For .navbar .fixed-top (with #app { margin-top: 60px; } it's better use scrollBehavior() { window.scrollTo(0,0); }
i have tried every method i could find, even official vue documentation and this is the only one that runs in all cases @SweetChillyPhilly thank you!
L
Lee Goddard

You could make use of behavior: smooth:

    moveTo () {
      let to = this.moveToDown
        ? this.$refs.description.offsetTop - 60
        : 0

      window.scroll({
        top: to,
        left: 0,
        behavior: 'smooth'
      })

      this.moveToDown = !this.moveToDown
    }

This one should be the accepted answer, thanks!
L
Lee Goddard

The best solution I've found for this is: https://router.vuejs.org/guide/advanced/scroll-behavior.html

Specifically:

    const router = new VueRouter({
      routes: [...],
      scrollBehavior (to, from, savedPosition) {
        return { x: 0, y: 0 }
      }
    })

This returns not defined for all to, from, savedPosition. How do you fix this ?
If you're not gonna use any of the variables you can just remove them.
L
Lee Goddard

Expanding on the answer from Vitaly Migunov, you can instead add directly from the router a scrollTo method to the window object. This way you won't need to add the function to every router link.

    const router = new Router({
      mode: 'history',
      routes: [...],
      scrollBehavior() {
        window.scrollTo(0,0);
      }
    })

Like the question mentions, scrollBehavior is not triggered when the path stays the same unfortunately. And that is the specific problem the person is having.
L
Lee Goddard

Use refs for scroll to certain section

    <template>
      <body>
        <div ref="section">
          // Your content section
        </div>
      </body>
    </template>
        
    export default class MyPage extends Vue {
      $refs!: {
        section: HTMLFormElement;
      };
    
      scrollToTop() {
        this.$refs.section.scrollTo(0, 0);
      }
    }

L
Lee Goddard

Basically, I think you want to scroll to the top of the page, unless an internal page location is specified (e.g. www.example.com/home#blah). All of the answers so far would ignore this location parameter, and just scroll to the top anyway.

    scrollBehavior(to, from, savedPosition) {
        //If there is no hash parameter when we change vue, scroll to top of page
        if (!to.hash) {
          return { x: 0, y: 0 }
        }
      }

We can check if there is a location parameter using to.hash, then only scroll to the top if no hash location is present.


V
Vukasin Koprivica

This worked for me:

const router = createRouter({
  history: createWebHashHistory(),
  routes,
  scrollBehavior() {
     document.getElementById('app').scrollIntoView({behavior:'smooth'});
  }
})

M
Mrkinix

I've tried all of the above answers and none did work for me; However I've tried this one and it did the job for me; Add this to your App.vue file

  updated() {
    this.$refs.main.scrollTo(0, 0)
  },

M
Mrkinix

Alternatively, this also worked for me:

const router = new VueRouter({
  mode: 'history',
  base: process.env.BASE_URL,
    scrollBehavior(to, from, savedPosition) {
      document.getElementById('app').scrollTop = 0
  },
  routes
})

k
kadakod

for vue3

const router = createRouter({
  history: createWebHistory(process.env.BASE_URL), 
  routes,
  scrollBehavior(to, from, savedPosition) {
    // always scroll to top
    return { top: 0 }
  },
})

A
Abhay

Vue Js have inbuilt support for scrolling if the browser supports history.pushState.

It is very easy to configure, Just provide the scrollBehavior function, when creating Vue router instance like below:

const router = new VueRouter({
  routes: [...],
  scrollBehavior (to, from, savedPosition) {
    // page scroll to top for all route navigations
    return { x: 0, y: 0 }
  }
})

For more options and detail about Vue Scroll Behavior click here


this solution will not work. scrollBehaviour is not called if the link leads to the current route, as specified by the OP.
sorry Techyaura, you jumped the gun a bit here, but thanks anyway
S
Sinan Eldem

Use this nice component: https://www.npmjs.com/package/vue-backtotop

<back-to-top text="Back to top"></back-to-top>