我有一个相对简单的问题,试图将内联脚本添加到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实际上在使用,我不想分享。
解决方案视场景而定。就像在我的情况下,我必须加载一个日历嵌入在一个react组件。
Calendly查找一个div并从它的data-url属性读取,并在该div中加载iframe。
第一次加载页面时一切正常:首先,呈现带有data-url的div。然后日历脚本添加到主体。浏览器下载并评估它,我们都高兴地回家了。
问题来了,当你导航离开,然后回到页面。这一次脚本仍然在主体中,浏览器不会重新下载和重新评估它。
Fix:
在componentWillUnmount上找到并删除脚本元素。然后重新安装,重复上述步骤。
进入.getScript美元。它是一个漂亮的jquery助手,接受一个脚本URI和一个成功回调。一旦加载了脚本,它就计算它并触发你的success回调。我所要做的是在我的componentDidMount $. getscript (url)。我的渲染方法已经有日历div。它工作顺利。
要在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);
}
使用Range.createContextualFragment有一个很好的变通方法。
/**
* Like React's dangerouslySetInnerHTML, but also with JS evaluation.
* Usage:
* <div ref={setDangerousHtml.bind(null, html)}/>
*/
function setDangerousHtml(html, el) {
if(el === null) return;
const range = document.createRange();
range.selectNodeContents(el);
range.deleteContents();
el.appendChild(range.createContextualFragment(html));
}
这适用于任意HTML,也保留上下文信息,如document.currentScript。