如何在 next.js 中的页面更改时卸载 next/script?

Jer*_*yal 12 html javascript reactjs next.js

我只想在某些页面上加载脚本。Next.js建议使用next/script标签。body但是,当我导航到某些不同的页面时,我仍然可以看到HTML末尾存在的脚本。

在此输入图像描述

import Script from "next/script";

const Comments = () => {
  return (
    <div className="giscus mt-16">
      <Script
        src="https://giscus.app/client.js"
        data-repo="GorvGoyl/Personal-Site-Gourav.io"
        data-repo-id="MDEwOlJlcG9zaXRvcnkyOTAyNjQ4MTU="
        data-category="Announcements"
        data-category-id="DIC_kwDOEU0W784CAvcn"
        data-mapping="pathname"
        data-reactions-enabled="0"
        data-emit-metadata="0"
        data-theme="light"
        data-lang="en"
        crossOrigin="anonymous"
        strategy="lazyOnload"
        onError={(e) => {
          console.error("giscus script failed to load", e);
        }}
      ></Script>
    </div>
  );
};
Run Code Online (Sandbox Code Playgroud)

我怀疑 Next.js 没有清理路由更改操作的脚本。如何确保脚本在页面更改时被删除?

Cha*_*rni 5

我面临着同样的问题。唯一适合我的解决方案是将页面重新加载routeChangeStart为. 我还在自定义 Hook 中制作了它,因此可以轻松重复使用。

定制挂钩

import { useRouter } from "next/router";
import { useEffect } from "react";

export default function useScript(url: string) {
    const router = useRouter();
    useEffect(() => {
        const script = document.createElement("script");
        script.src = url;
        script.async = true;
        document.body.appendChild(script);

        // Needed for cleaning residue left by the external script that can only be removed by reloading the page
        const onRouterChange = (newPath: string) => {
            window.location.href = router.basePath + newPath;
        };
        router.events.on("routeChangeStart", onRouterChange);

        return () => {
            router.events.off("routeChangeStart", onRouterChange);

            document.body.removeChild(script);
        };
    }, [router, url]);
}
Run Code Online (Sandbox Code Playgroud)

说明:

  • 该钩子创建新的脚本元素,将其 url 设置为提供的 url 并将其附加到正文
  • 导入脚本很容易,困难的部分是删除它以及它在 window 对象上的 mailny 后面留下的所有残留物,简单而简单的方法是重新加载页面
  • 因此,我们为路由更改添加事件侦听器,然后重定向到该页面,以便整个页面刷新并且所有先前的 js 脚本都被卸载

用法:

只需要使用 javascript 的 url 调用 useScript

import React from "react";
import NavBar from "../src/components/NavBar";
import useScript from "../src/hooks/useScript";

type Props = {};

const ScriptLoader = (props: Props) => {
    useScript("/js/theScript.js");
    return (
        <>
            <NavBar />

            <div className="container">This is normal Page</div>
        </>
    );
};

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

笔记:

如果您想从脚本访问窗口对象上设置的属性,最好添加 setTimeout 来检查该对象是否存在,因为加载脚本可能需要一些时间,之后您可以将某些标志设置为 true