我有一个相对简单的问题,试图将内联脚本添加到React组件。到目前为止我有:
'use strict';
import '../../styles/pages/people.scss';
import React, { Component } from 'react';
import DocumentTitle from 'react-document-title';
import { prefix } from '../../core/util';
export default class extends Component {
render() {
return (
<DocumentTitle title="People">
<article className={[prefix('people'), prefix('people', 'index')].join(' ')}>
<h1 className="tk-brandon-grotesque">People</h1>
<script src="https://use.typekit.net/foobar.js"></script>
<script dangerouslySetInnerHTML={{__html: 'try{Typekit.load({ async: true });}catch(e){}'}}></script>
</article>
</DocumentTitle>
);
}
};
我也试过:
<script src="https://use.typekit.net/foobar.js"></script>
<script>try{Typekit.load({ async: true });}catch(e){}</script>
这两种方法似乎都不能执行所需的脚本。我猜我错过了一件简单的事。有人能帮忙吗?
PS:忽略foobar,我有一个真正的id实际上在使用,我不想分享。
有点晚了,但我决定创建我自己的@Alex Macmillan的答案后,这是通过传递两个额外的参数;放置脚本的位置,如或和设置async为true/false,这里是:
import { useEffect } from 'react';
const useScript = (url, position, async) => {
useEffect(() => {
const placement = document.querySelector(position);
const script = document.createElement('script');
script.src = url;
script.async = typeof async === 'undefined' ? true : async;
placement.appendChild(script);
return () => {
placement.removeChild(script);
};
}, [url]);
};
export default useScript;
调用它的方式与本文中接受的答案完全相同,但有两个额外的参数(再次):
// First string is your URL
// Second string can be head or body
// Third parameter is true or false.
useScript("string", "string", bool);
编辑:事情变化很快,这是过时的-见更新
您是希望在每次呈现该组件时,还是在将该组件挂载到DOM时,一次又一次地获取并执行脚本?
也许可以试试这样的方法:
componentDidMount () {
const script = document.createElement("script");
script.src = "https://use.typekit.net/foobar.js";
script.async = true;
document.body.appendChild(script);
}
但是,只有当你想要加载的脚本不能作为模块/包使用时,这才真正有用。首先,我总是:
在npm上查找包
下载并安装在我的项目包(npm install typekit)
导入我需要的包(import Typekit from ' Typekit ';)
这可能就是你安装例子中的react和react-document-title包的方式,npm上有一个Typekit包可用。
更新:
现在我们有了钩子,一个更好的方法可能是像这样使用useEffect:
useEffect(() => {
const script = document.createElement('script');
script.src = "https://use.typekit.net/foobar.js";
script.async = true;
document.body.appendChild(script);
return () => {
document.body.removeChild(script);
}
}, []);
这使得它成为自定义钩子(例如:hooks/useScript.js)的一个很好的候选人:
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;
可以这样使用:
import useScript from 'hooks/useScript';
const MyComponent = props => {
useScript('https://use.typekit.net/foobar.js');
// rest of your component
}
要在head tag <head>中添加脚本标签或代码,请使用react-helmet包。它很轻,有很好的文档。
在script标签中添加Js代码
function htmlDecode(html) {
return html.replace(/&([a-z]+);/ig, (match, entity) => {
const entities = { amp: '&', apos: '\'', gt: '>', lt: '<', nbsp: '\xa0', quot: '"' };
entity = entity.toLowerCase();
if (entities.hasOwnProperty(entity)) {
return entities[entity];
}
return match;
});
}
render() {
const scriptCode = `<script type="text/javascript">
{(function() {
window.hello={
FIRST_NAME: 'firstName',
LAST_NAME: 'lastName',
};
})()}
</script>`
return(
<div dangerouslySetInnerHTML={{ __html: this.htmlDecode(scriptCode) }} />;
);
}
这段代码可以通过console.log(windows.hello)进行测试。
Alex Mcmillan提供的答案对我帮助最大,但对于更复杂的脚本标记不太适用。
我稍微调整了他的答案,提出了一个解决方案的长标签与各种功能,另外已经设置“src”。
(对于我的用例,脚本需要生活在头部,这是反映在这里):
componentWillMount () {
const script = document.createElement("script");
const scriptText = document.createTextNode("complex script with functions i.e. everything that would go inside the script tags");
script.appendChild(scriptText);
document.head.appendChild(script);
}
老实说,对于React来说,不要在头文件中添加<script>标签。这是一个痛苦的屁股得到一个回调时,他们已经完全加载。相反,使用像@charlietango/useScript这样的包在需要时加载脚本,并在脚本完成时获得状态更新。
使用示例:
import React from 'react'
import useScript, { ScriptStatus } from '@charlietango/use-script'
const Component = () => {
const [ready, status] = useScript('https://api.google.com/api.js')
if (status === ScriptStatus.ERROR) {
return <div>Failed to load Google API</div>
}
return <div>Google API Ready: {ready}</div>
}
export default Component
PS.如果你使用redux来告诉其他组件你的脚本何时加载,并且像我一样使用redux-persist,不要忘记在你的redux-persist设置中包含一个修饰符,它总是在redux备份中将脚本加载的redux值设置为false。