NextJS 脚本标签
所以我已经尝试了很长时间了。
在这个网站上,我需要能够放置一个脚本标记,该标记将嵌入联系表单和新闻通讯注册表单等到特定页面。因此,例如在联系页面上,联系表单脚本标记将生效。
我尝试了许多不同的方法,但我无法获得我想要的结果,因为这似乎是一件非常基本的事情。
我发现它最初似乎运行良好,脚本标记有效,我在页面上看到了我期望的内容。但是当您离开该页面并返回时,脚本标记不会显示。只有当我再次刷新页面时,脚本标记应该输出的内容才会出现。
我假设发生这种情况是因为使用 Link 标记后,网站不会在导航之间重新加载,而是像 SPA 一样工作,无需重新加载,但正是这种刷新触发了脚本标记的执行。
在我对此的研究中,我看到人们建议不要使用 Link 标记,而只使用标记,因此当导航到页面时,它必须重新加载并强制显示脚本标记。只是在我的情况下,这不是一个真正的选择,因为我无法判断客户端决定在哪个页面输出脚本标记,因为该网站是完全动态的,并且能够通过 CMS 进行构建。
我试过:
使用脚本执行 dangerlySetInnerHTML 技巧。不幸的是,正如我上面描述的,同样的事情发生了
<div
dangerouslySetInnerHTML={{__html: `<script src=""></script>`}}
/>
我也尝试过使用 next 的内置脚本标记 https://nextjs.org/docs/api-reference/next/script 和所有不同的策略道具。不幸的是,脚本内容要么根本没有显示,要么表现得和上面一样。
我还尝试过创建一个辅助函数,该函数仅在导航到页面后使用 useEffect 来插入脚本标记,如下所示:
import { useEffect } from "react"
const useScript = (url) => {
useEffect(() => {
const script = document.createElement("script")
script.src = url
script.async = true
document.body.appendChild(script)
return () => {
document.body.removeChild(script)
}
}, [url])
}
export default useScript;
然后在组件输出到页面:
<div>
{useScript("...")}
</div>
这确实有效!每次导航到带有脚本的页面时,它都会输出脚本标记的内容 - 无需刷新页面。唯一的问题是脚本标记的内容始终输出在页面底部、页脚下方和所有内容。与实际 useScript 在组件中的位置相反。
我尝试通过将脚本附加到组件中已经存在的 div 中来改变 useEffect 的工作方式:
import { useEffect } from "react"
const useScript = (url) => {
useEffect(() => {
const script = document.createElement("script")
script.src = url
script.async = true
script.defer = true
document.getElementById('scriptEx').appendChild(script)
return () => {
document.body.removeChild(script)
}
}, [url])
}
export default useScript;
但由于某种原因,这与之前的设置不同。导航到页面时,脚本标记的内容不会再次显示。
我发现的最后一个方法每次都有效,但似乎是一个非常荒谬的方法是将脚本标记放在 iFrame 中:
<iframe
srcDoc={`
<!doctype html>
<html>
<head>
</head>
<body>
<div>
<script src="..."></script>
</div>
</body>
</html>
`}
/>
一定有办法做这个看似简单的事情。
如果有人能提供帮助,我将不胜感激!
编辑 :下面是我使用 Next 的 Script 标签所看到的示例: https://i.sstatic.net/gMumx.png
下面是组成该页面的 jsx:
import Script from "next/script";
const example = () => {
return (
<div>
The Nav is above this
<div>
<p>Container for the form</p>
<Script src="//basingstokegov.uk.com/resources/sharing/embed.js?sharing=lp-embed&domain=basingstokegov.uk.com&id=3IWH-BN7%2Fthank-you%22" async />
</div>
The footer is below this
</div>
)
}
export default example
如果您使用的是 NextJs,解决方案非常简单。从 v11.0 开始,Next 团队从库 next/script 中引入了 Script 组件 ,它类似于库 next/head 中的 Head 组件。基本上您需要做的是:
import Script from 'next/script'
export default function Home(){
return(
<>
<Script src="#" async />
</>
)
}
您可以在此处阅读有关 Next 文档中脚本组件的更多信息: https://nextjs.org/docs/basic-features/script
我认为您应该从具有 id
scriptEx
的元素中删除子元素,就像从主体中删除脚本一样。我认为您所要做的就是放入
return () => {
document.getElementById('scriptEx').removeChild(script)
}
而不是
return () => {
document.body.removeChild(script)
}
编辑
我认为因为您正在使用 NextJS,所以您需要验证
document
是否存在于
useEffect
的顶部。如下所示:
useEffect(() => {
// If there is no window
if (typeof window === "undefined") return;
}, [])