我正在尝试使用ReactJS嵌入一个Gist,但是我收到以下错误:
无法在'Document'上执行'write':除非明确打开,否则无法从异步加载的外部脚本写入文档。
这是我的组件:
var EmbeddedGist = React.createClass({
render: function() {
return (
<div id="gist-container" />
);
},
componentDidMount: function() {
var src = this.props.srcUrl + ".js";
$('#gist-container').html('<script src="' + src + '"></script>');
}
});
我从另一个组件中调用它,如下:
<EmbeddedGist srcUrl="https://gist.github.com/awalGarg/a5bd02978cecf3703f61" />
关于如何使这项工作的任何想法?
答案 0 :(得分:11)
Gist嵌入脚本使用document.write
将构成嵌入式Gist的HTML写入文档的HTML中。但是,当您的React组件添加script
标记时,写入文档就太晚了。
虽然您无法动态地将Gist嵌入脚本添加到您的页面,但可以通过JSONP 获取Gist的内容并将其写入文档你自己。这是一个采用gist
属性和可选file
属性并为您呈现要点的组件。
var EmbeddedGist = React.createClass({
propTypes: {
gist: React.PropTypes.string.isRequired, // e.g. "username/id"
file: React.PropTypes.string // to embed a single specific file from the gist
},
statics: {
// Each time we request a Gist, we'll need to generate a new
// global function name to serve as the JSONP callback.
gistCallbackId: 0,
nextGistCallback: function() {
return "embed_gist_callback_" + EmbeddedGist.gistCallbackId++;
},
// The Gist JSON data includes a stylesheet to add to the page
// to make it look correct. `addStylesheet` ensures we only add
// the stylesheet one time.
stylesheetAdded: false,
addStylesheet: function(href) {
if (!EmbeddedGist.stylesheetAdded) {
EmbeddedGist.stylesheetAdded = true;
var link = document.createElement('link');
link.type = "text/css";
link.rel = "stylesheet";
link.href = href;
document.head.appendChild(link);
}
}
},
getInitialState: function() {
return {
loading: true,
src: ""
};
},
componentDidMount: function() {
// Create a JSONP callback that will set our state
// with the data that comes back from the Gist site
var gistCallback = EmbeddedGist.nextGistCallback();
window[gistCallback] = function(gist) {
if (this.isMounted()) {
this.setState({
loading: false,
src: gist.div
});
EmbeddedGist.addStylesheet(gist.stylesheet);
}
}.bind(this);
var url = "https://gist.github.com/" + this.props.gist + ".json?callback=" + gistCallback;
if (this.props.file) {
url += "&file=" + this.props.file;
}
// Add the JSONP script tag to the document.
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = url;
document.head.appendChild(script);
},
render() {
if (this.state.loading) {
return <div>loading...</div>;
} else {
return <div dangerouslySetInnerHTML={{__html: this.state.src}} />;
}
}
});
你可以像这样使用它:
var app = (
<div>
<EmbeddedGist gist="BinaryMuse/a57ae1a551472e06b29a" file="restful.js" />
<hr />
<EmbeddedGist gist="BinaryMuse/bb9f2cbf692e6cfa4841" />
</div>
);
React.render(app, document.getElementById("container"));
查看this example of it working on JSfiddle:http://jsfiddle.net/BinaryMuse/nrb6zxfw/
改善此问题的一种方法是确保具有EmbeddedGist
或gist
道具更改的现有file
组件将更新为通过挂钩{{1}来使用新数据}。
答案 1 :(得分:2)
我使用componentWillRecieveProps更新了道具,如binaryMuse建议。
做了类似的事情:
componentDidMount: function() {
this._getGistData(this.props.gist,this.props.file);
},
componentWillReceiveProps: function (nextProps) {
if (this.props.gist !== nextProps.gist || this.props.file !== nextProps.file) {
this._getGistData(nextProps.gist,nextProps.file);
}
},
其中_getGistData只是componentDidMount
中的原始代码