Nuxt 3 scrollBehavior – 滚动到哈希 url,页面转换完成后,当主要滚动页面元素不是根时

问题描述 投票:0回答:0

我的应用程序不使用文档/主体作为滚动主体,它使用带有 id

#overflow
的自定义 div 作为每个页面的主要滚动元素。这样做的原因是为了利用 3D 变换来实现视差和各种其他过渡功能,但我不会详细介绍。 所以请接受我的用例不需要在根上使用溢出。

因为我没有使用根作为我的滚动元素,所以默认路由器滚动链接到哈希 URL——比如

/some-page#some-hash
不起作用。因此,我需要覆盖默认的滚动行为,以便捕获页面上具有匹配 ID 的元素的任何哈希 URL 并适当地滚动到。但是,我似乎无法正常工作。我尝试了多种不同的方法:

在插件中使用 page:finish 钩子:

export default defineNuxtPlugin((nuxtApp) => {
  nuxtApp.hook('page:finish', () => {
    const overflow = document.getElementById("overflow");
    const hash = window.location.hash;
    if (overflow) {
      if (hash) {
        const section = document.getElementById(hash.replace('#',''));
        const distance = section ? section.getBoundingClientRect().top +  window.scrollY - 120 : null;
        overflow.scrollTo({top: distance, behavior: 'smooth'});
      } else {
        overflow.scrollTo(0, 0);
      }
    } else {
      window.scrollTo(0, 0);
    }
  })
})

覆盖 scrollBehavior 并等待在插件的异步函数中在页面上找到元素:

export default defineNuxtPlugin((nuxtApp) => {
  nuxtApp.$router.options.scrollBehavior = async (to, from, savedPosition) => {
    if (savedPosition) {
      return savedPosition;
    }

    const findEl = async (hash, x = 0) => {
      return (
        document.querySelector(hash) ||
        new Promise((resolve) => {
          if (x > 0) {
            return resolve(document.querySelector("#overflow"));
          }
          setTimeout(() => {
            resolve(findEl(hash, 1));
          }, 100);
        })
      );
    };

    const overflow = await document.getElementById("overflow");
    if (overflow) {
      if (to.hash) {
        const el = await findEl(to.hash);
        //const distance = el ? el.getBoundingClientRect().top +  window.scrollY - 120 : null;
        const distance = el ? el.getBoundingClientRect().top - 120 : null;
        console.log(distance);
        if ("scrollBehavior" in overflow.style) {
          return el.scrollTo({ top: 400, behavior: "smooth" });  // everything above works but just doesn't action the final scroll function   
         }
      }
    }
  };
});

在 nuxt.config 的全局页面转换中使用 onAfterEnter 事件:

export default defineNuxtConfig({
  app: {
    pageTransition: {
      name: 'page',
      mode: 'out-in',
      onAfterEnter: () => {
        const hash = window.location.hash;
        if (hash) {
          const section = document.getElementById(hash.replace('#',''));
          const overflow = document.getElementById('overflow');
          const distance = section ? section.getBoundingClientRect().top +  window.scrollY - 120 : null;
          if (section && distance) {
            overflow.scrollTo({top: distance, behavior: 'smooth'});
          }
          
        }
      }
      //duration:{ enter: 1000, leave: 800 }
    },
}
});

在页面转换完成后呈现的页面组件上的挂载钩子中。

onMounted(() => {
const overflow = document.getElementById("overflow");
    const hash = window.location.hash;
    if (overflow) {
      if (hash) {
        const section = document.getElementById(hash.replace('#',''));
        const distance = section ? section.getBoundingClientRect().top +  window.scrollY - 120 : null;
        overflow.scrollTo({top: distance, behavior: 'smooth'});
      } else {
        overflow.scrollTo(0, 0);
      }
    } else {
      window.scrollTo(0, 0);
    }

}) 

以上尝试均无效。有人有替代解决方案吗?

vue.js nuxt.js vuejs3 nuxt3
© www.soinside.com 2019 - 2024. All rights reserved.