Nuxt 3 使用哈希链接平滑滚动

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

在我的 Nuxt.js 3 项目中,我想实现单页导航。我遵循了以下文章,但没有成功。有什么建议吗?

scroll routes anchor nuxtjs3
5个回答
2
投票

在 Nuxt.js 3 中执行此操作的正确方法是在

plugins/
目录中创建“router.scrollBehaviour.js”文件。其内容应该是

import { defineNuxtPlugin } from "#app";

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("#app"));
          }
          setTimeout(() => {
            resolve(findEl(hash, 1));
          }, 300);
        })
      );
    };

    if (to.hash) {
      const el = await findEl(to.hash);

      if ("scrollBehavior" in document.documentElement.style) {
        console.log("hash path hit scroll to");
        return window.scrollTo({ top: el.offsetTop, behavior: "smooth" });
      } else {
        return window.scrollTo(0, el.offsetTop);
      }
    }
    return { left: 0, top: 0, behaviour: "smooth" };
  };
})

1
投票

在 Nuxt.js 3 中,您无需插件即可完成此操作。只需将“app/router.options.ts”放置在项目的根目录中,然后添加以下代码即可:



    import type { RouterConfig } from "@nuxt/schema";
    
    export default {
      scrollBehavior(to, from, savedPosition) {
        if(savedPosition)
          return savedPosition;
    
        if (to.hash && to.path == from.path) {
           const el = document.querySelector(to.hash);
        return { top: el.offsetTop, left: 0, behavior: "smooth" };
        }
    
        return {
          top: 0,
          left: 0
        }
      }
    };


0
投票

我更喜欢这个:

插件/scroll-behavior.client.ts

import { useRouter } from "vue-router";

export default async function () {
  if (typeof window !== "undefined") {
    const router = useRouter();

    router.afterEach(async (to, from) => {
      if (to.hash) {
        const targetElement = document.querySelector(to.hash);

        if (targetElement) {
          await targetElement.scrollIntoView({
            behavior: "smooth",
            block: "start",
            inline: "nearest",
          });
          return;
        }
      }

      window.scrollTo({ top: 0, behavior: "smooth" });
    });
  }
}

在 nuxt.config.ts 中添加以下内容:

  plugins: [
    { src: '~/plugins/scroll-behavior.client.ts', mode: 'client' }
  ]

然后,在你的组件中,引用带有 id 的内容,比如 id="about" 页面上有一个按钮,可以顺利地显示 about 哈希值。

<nuxt-link :to="{ hash: '#about' }" class="btn btn-lg btn-warning mx-1">Learn more</nuxt-link>

0
投票

为 Nuxt3 定义 pulgin 文件 plugins/scroll-behavior.client.ts 就像 Kaiser 提到的, 但我必须修改它才能适用于 Nuxt3。主要区别是您应该在转换实际发生之前使用 beforeEach 调用动画。否则你最终会尝试为已经存在的位置设置动画。延迟承诺弥补了过渡时间,如果你把它缩短,过渡就会更快。这适用于单页面,但可能需要升级才能在页面之间导航锚点。

      export default defineNuxtPlugin(async function () {
          if (typeof window !== "undefined") {
        
            const router = useRouter();
        
            router.beforeEach((to) => {
              if (to.hash) {
                const targetElement = document.querySelector(to.hash);
                if (targetElement) {
                  targetElement.scrollIntoView({
                      behavior: "smooth"
                  })
                  const p:Promise<boolean> = new Promise((resolve)=>{
                    setTimeout(()=>{
                      resolve(true);
                    },1000)
                  })
                  return p
                }
              }
        
              window.scrollTo({ top: 0, behavior: "smooth" });
            });
          }
        });

并像前面提到的那样在 nuxt.config.ts 中设置插件:

  plugins: [
    { src: '~/plugins/scroll-behavior.client.ts', mode: 'client' }
  ]

然后您可以使用带有哈希值的导航:

<NuxtLink :to="{path: '/', hash: '#anchor1'}">
          <div class="button">Link 1</div>
</NuxtLink>

...

<div id="anchor1"> Target content block </div>

0
投票

在 Nuxt 3 中使用插件不是实现此目的的方法 - 请看这里:https://github.com/nuxt/nuxt/issues/22663

© www.soinside.com 2019 - 2024. All rights reserved.