【问题标题】:How to embed a Gist using ReactJS如何使用 ReactJS 嵌入 Gist
【发布时间】:2015-05-24 23:18:38
【问题描述】:

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

在“文档”上执行“写入”失败:除非明确打开,否则无法从异步加载的外部脚本写入文档。

这是我的组件:

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" />

关于如何完成这项工作的任何想法?

【问题讨论】:

    标签: reactjs gist


    【解决方案1】:

    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 组件具有gistfile 属性更改将通过挂钩componentWillReceiveProps 更新以使用新数据。

    【讨论】:

    【解决方案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 中的原始代码

    【讨论】:

    • 这比标记的答案更小更简单,是否一样好?
    • B鼠是谁?
    • @SuperUberDupe 在建议的答案中。在答案的最后,他建议“改进这一点的一种方法是确保现有的 EmbeddedGist 组件具有其 gist 或文件属性更改将更新以通过挂钩到 componentWillReceiveProps 来使用新数据。”
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-12-07
    • 1970-01-01
    • 1970-01-01
    • 2019-12-20
    • 2021-04-24
    • 2013-04-21
    • 2015-07-13
    相关资源
    最近更新 更多