Javascript 如何在react中加载自定义脚本?
这有点类似于这个问题: 但在我的例子中,我加载的脚本如下:Javascript 如何在react中加载自定义脚本?,javascript,reactjs,Javascript,Reactjs,这有点类似于这个问题: 但在我的例子中,我加载的脚本如下: <script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start': new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0], j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','ID');</script>
<!-- End Google Tag Manager -->
这很好,但是如果我在加载的脚本中有一个函数,我将如何正确执行它?通常,可以使用
危险的HTML
属性更新react中的HTML元素。
但是对于要执行的脚本来说,这是行不通的,正如本文中所讨论的
必须实现这一点的一个选项是,使用文档范围API将元素附加到新文档上下文中
下面是一个工作示例。
请注意,我对您的脚本进行了一些调整,以显示一些自定义脚本的方法
const{useState,useRef,useffect,memo}=React;
常量MyCustomScriptComponent=()=>{
const[includeScript,setIncludeScript]=useState(false)
//只是一些自定义文字脚本定义的示例
const labelName='dataLayer'
const gtmId='ID'//您的GTM ID
//声明自定义文字字符串
常量scriptToInject=`
(功能(w、d、s、l、i){
const gtmStart=new Date().getTime();
w[l]=w[l]|【】;w[l]。推送({'gtm.start':
gtmStart,事件:'gtm.js'});var f=d.getElementsByTagName[0],
j=d.createElement,dl=l!=“数据层”?“&l=”+l:“”;j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
log(“在gtmStart加载:”,gtmStart);
})(窗口,文档,'script','${labelName}','${gtmId}');
log(“使用id“${gtmId}”获取GTM);
`
常量脚本=备忘录({script})=>{
const divRef=useRef(null);
useffect(()=>{
if(divRef.current==null){
返回;
}
//创建将执行脚本的上下文片段
//当心安全问题!!
const doc=文档
.createRange()
.createContextualFragment(脚本)
//清除div HTML,并用脚本附加doc片段
divRef.current.innerHTML=“”
divRef.current.appendChild(doc)
})
返回
})
const-toggleIncludeScript=()=>setIncludeScript((include)=>!include)
返回(
{includeScript&&}
自定义脚本{includeScript?'loaded!':“not loaded.”
单击以加载
)
}
ReactDOM.render(,document.getElementById('app'))
在现场试一试
如需更多参考,您可以在此中找到更多注入脚本的替代方案。若要添加这样的随机脚本,您可以:
<body>
<div id="root"></div>
<script>/* your script here */</script>
</body>
3。代码拆分
最后,如果您希望在某个时间点动态加载一段js代码,同时确保它不是起始包的一部分,那么可以使用动态导入进行代码拆分
函数应用程序(){
函数handleLoadScript(){
导入(“/您的脚本”)
.then({functionFromModule})=>{
//使用functionFromModule
})
.catch(错误=>{
//处理失败
});
};
返回载荷;
}
将该函数设为全局变量,然后像这样在任何地方使用它:gloabl.functionFromScript
。另外,为什么要这样做呢?必须有一个更好的解决方案来解决您的实际用例。另外,如果您希望始终加载自定义脚本,只需将其添加到index.html
中,而不是通过所有的js将脚本标记附加到body上。您是正确的。上面的脚本将被移动到index.html,但我有一个不同的场景,其中添加了一些类似的内容,但它仅用于特定场景,因此,为了不加载在用户到达特定场景之前基本上只是停留在那里的全局脚本,这并不理想,所以我认为一旦用户触发所需的脚本,我会加载它行为。我希望避免将其保存在全局变量中,从而避免出现相同的情况。我有一个钩子,我想触发一个以类似于上面的方式编写的脚本,但不知道如何正确地执行它。你不能将你的函数附加到一个对象,然后将它公开给其他脚本使用吗。是的,新对象最终将附加到全局/窗口,但还可以执行其他操作。
<body>
<div id="root"></div>
<script>/* your script here */</script>
</body>
// index.js
import "../path/to/your/script-file";
function App() {
function handleLoadScript() {
import('./your-script')
.then(({ functionFromModule }) => {
// Use functionFromModule
})
.catch(err => {
// Handle failure
});
};
return <button onClick={handleLoadScript}>Load</button>;
}