如何在ReactJS中嵌入Gist

5
我正在尝试使用ReactJS嵌入Gist,但是出现以下错误:

Failed to execute 'write' on 'Document': It isn't possible to write into a document from an asynchronously-loaded external script unless it is explicitly opened.

这是我的组件代码:
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" />

有什么想法可以让这个工作起来吗?
2个回答

12

Gist嵌入脚本使用document.write将组成嵌入式Gist的HTML写入文档的HTML中。但是,当您的React组件添加script标记时,已经太晚在文档中写入了。

虽然您无法动态地将Gist嵌入脚本添加到页面中,但是您可以通过JSONP获取Gist的内容,并将其自己写入文档中。下面是一个组件,它接受gist属性和可选的file属性,并为您呈现Gist。

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"));

请查看JSfiddle上这个示例http://jsfiddle.net/BinaryMuse/nrb6zxfw/

改进此方法的一种方式是确保已有的EmbeddedGist组件在其gistfile属性更改时,通过链接到componentWillReceiveProps来更新为新数据。


1
我制作了一个ES6版本:https://gist.github.com/aVolpe/b364a8fcd10f1ba833d97e9ab278f42c - Arturo Volpe

2

我按照binaryMuse的建议,使用componentWillReceiveProps更新props来实现它。

具体做法如下:

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中原始代码的简单表述。


这个比标记答案小得多,也更简单,但是它一样好吗? - SuperUberDuper
谁是B鼠? - SuperUberDuper
@SuperUberDupe在建议的答案中提到了这一点。在答案的末尾,他建议:“改进的一种方式是通过钩入componentWillReceiveProps来确保已经存在的EmbeddedGist组件在其gist或file prop更改时会更新以使用新数据。” - Kinnza

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接