Next.js 内联脚本仅加载一次

Yad*_*rus 6 javascript next.js

我在 Next.js 应用程序中实现了Tiny Slider,它需要页面上的内联脚本来控制滑块的行为。现在,虽然脚本在我第一次启动 index.js 时正确加载,但是每当我使用 Link 导航到另一个页面并返回到 index.js 时,脚本都不会加载。

这是我在 index.js 中编写脚本的方式

 {/* Script */}
        <Script id='tester'>
          {`
            var slider = tns({
              container: '.my-slider',
              items: 6,
              autoplay: true,
              autoplayTimeout: 2000,
              gutter: 20,
              autoplayButtonOutput: false,
              controls: false,
              navPosition: 'bottom',
              nav: false,
              mouseDrag: true,
              arrowKeys: true,
              responsive: {
                300: {
                  items: 2,
                  gutter: 50,
                  center: true,
                  fixedWidth: 250,
                },
                700: {
                  items: 3,
                  gutter: 50,
                  center: true,
                  fixedWidth: 250,
                },
                1440: {
                  items: 3,
                  gutter: 50,
                  fixedWidth: 250,
                  center: true,
                }
              }
            });
          `}
        </Script>
Run Code Online (Sandbox Code Playgroud)

我需要每次加载 index.js 时加载脚本,而不仅仅是第一次。关于我如何做到这一点有什么想法吗?整个代码在这里 - https://github.com/YaddyVirus/Esttheva

Log*_*son 4

以下是将tiny-slider 添加到 next.js 应用程序的步骤。

  1. 添加pages/_document.js来加载样式
// pages/_document.js
import { Html, Head, Main, NextScript } from 'next/document'

export default function Document() {
  return (
    <Html>
      <Head>
        <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/tiny-slider/2.9.2/tiny-slider.css" />
      </Head>
      <body>
        <Main />
        <NextScript />
      </body>
    </Html>
  )
}
Run Code Online (Sandbox Code Playgroud)
  1. 这是加载滑块的示例页面
import { useEffect, useRef } from "react";

const App = () => {
  const ref = useRef(true);

  useEffect(() => {
    let slider;
    // Tiny slider only can be loaded once and can only be loaded clint side
    if (typeof window !== "undefined" && ref.current) {
      ref.current = false;
      // Lazy load the slider code client side
      import("tiny-slider").then((x) => {
        slider = x.tns({
          container: ".slider",
          items: 3,
          slideBy: "page",
          autoplay: true
        });
      });
    }
    // Destory the slider when it is unmouted
    return slider?.destroy();
  }, []);

  return (
    <div>
      <div className="slider">
        <div>1</div>
        <div>2</div>
        <div>3</div>
        <div>4</div>
        <div>5</div>
        <div>6</div>
      </div>
    </div>
  );
};

export default App;
Run Code Online (Sandbox Code Playgroud)

代码沙箱链接:https://codesandbox.io/s/tina-slider-nextjs-0z8zi6 ?file=/pages/index.js:0-806

以下是有关该解决方案的几个要点

  • 跟踪ref钩子是否已经被调用(从 React 18 开始,钩子在开发模式下被调用两次)
  • 我们用它typeof window !== "undefined"来确保tiny-window仅在客户端加载,而不是在服务器上加载(这会导致“窗口未定义”错误)
  • 我们根据文档调用该tns函数