vue.jsvuejs3

Why is VueJS Routers savedPosition always 0? How can I store the scroll position by myself?


I have a strange issue with the VueJS Router and its built-in scrollBehaviour-feature.

I want to achieve that on back-navigation, the browser would scroll down to the original position where the user previously clicked for navigation into a child page.

I am using the built-in ScrollBehaviour Feature: https://router.vuejs.org/guide/advanced/scroll-behavior

My implementation is this:

  const router = createRouter({
    scrollBehavior(to, from, savedPosition) {
      if (savedPosition) {
        return new Promise((resolve, reject) => {
          setTimeout(() => {
            console.log('Saved Position:', savedPosition)
            resolve({ left: 0, top: savedPosition.top, y: savedPosition.top, behavior: 'smooth' });
          }, 800)
        })
      } else {
        return new Promise((resolve, reject) => {
          setTimeout(() => {
            resolve({ top: 0, behavior: 'smooth' });
          }, 800)
        })
      }
    },

So far, it doesn't work well. It most of the cases, the savedPosition is just top: 0.

Google Chrome Desktop: works mostly always, sometimes not
Google Chrome on iOS: don't work at all
Safari Desktop Mac: don't work at all. savedPosition is always `top: 0`
Safari iOS: don't work at all. savedPosition is always `top: 0`

Apparently I have to save the scroll position by myself. How can I do this and where?


Solution

  • i think i had the same problem, and "scroll-behaviour" feature didnt work for me either. in one of my projects i did this:

    1. in router i added meta: { saveScrollPosition: true }, to routes i wanted to have scroll positions saved

    2. then just using beforeEach:

      router.beforeEach((to, from, next) => {
      setTimeout(() => {
       if (from.meta.saveScrollPosition) {
           saveScrollPosition(from.path, window.scrollY);
         }
           next();
         }, 0);
      });
      
    3. scrollManager.js:

       let scrollPositions = {};
      
       export function saveScrollPosition(path, position) {
         scrollPositions[path] = position;
       }
      
       export function getScrollPosition(path) {
         return scrollPositions[path] || 0;
       }
      
    4. then in every page i wanted the scroll to be restored(this is homepage as an example):

       onMounted(() => {
         const scrollY = getScrollPosition("/home");
         window.scroll(0, scrollY);
       });
      
    5. and dont forget imports import { getScrollPosition } from "@/scrollManager";

    i feel like this is kind of barbaric, but it worked for me at that time.