React:使用dangerouslySetInnerHTML插入时脚本标记不起作用

met*_*ors 19 html javascript script-tag reactjs

我正在尝试使用React中的dangerouslySetInnerHTML属性设置从我的服务器发送的html以显示div内部.我里面也有脚本标签,并使用html中定义的函数.我在这里用JSFiddle做了错误的例子.

这是测试代码:

var x = '<html><scr'+'ipt>alert("this.is.sparta");function pClicked() {console.log("p is clicked");}</scr'+'ipt><body><p onClick="pClicked()">Hello</p></body></html>';

var Hello = React.createClass({
  displayName: 'Hello',
  render: function() {
    return (<div dangerouslySetInnerHTML={{__html: x}} />);
  }
});
Run Code Online (Sandbox Code Playgroud)

我检查并将脚本标记添加到DOM,但无法调用该脚本标记中定义的函数.如果这不是正确的方法,我可以通过其他任何方式注入脚本标记的内容.

小智 26

我创建了一个 React 组件,它的工作原理非常相似,dangerouslySetInnerHtml但另外它会执行它在 html 字符串上找到的所有 js 代码,检查一下,它可能对你有帮助:

https://www.npmjs.com/package/dangerously-set-html-content


Das*_*ith 16

这里有一个简单的方法来完成它,有点解释这里发生了什么,你通过正则表达式提取脚本内容,只使用react渲染html,然后在组件安装后脚本标签中的内容在全局范围内运行.

var x = '<html><scr'+'ipt>alert("this.is.sparta");function pClicked() {console.log("p is clicked");}</scr'+'ipt><body><p onClick="pClicked()">Hello</p></body></html>';

var extractscript=/<script>(.+)<\/script>/gi.exec(x);
x=x.replace(extractscript[0],"");

var Hello = React.createClass({
  displayName: 'Hello',
  componentDidMount: function() {
    // this runs the contents in script tag on a window/global scope
    window.eval(extractscript[1]);

  },
  render: function() {
    return (<div dangerouslySetInnerHTML={{__html: x}} />);
  }
});

ReactDOM.render(
  React.createElement(Hello),
  document.getElementById('container')
);
Run Code Online (Sandbox Code Playgroud)


emi*_*l.c 5

我认为您不需要在+此处使用串联()。

var x = '<html><scr'+'ipt>alert("this.is.sparta");function pClicked() {console.log("p is clicked");}</scr'+'ipt><body><p onClick="pClicked()">Hello</p></body></html>';
Run Code Online (Sandbox Code Playgroud)

我认为您可以做到:

var x = '<html><script>alert("this.is.sparta");function pClicked() {console.log("p is clicked");}</script><body><p onClick="pClicked()">Hello</p></body></html>';
Run Code Online (Sandbox Code Playgroud)

由于它已经传递给dangerouslySetInnerHTML了。

但是,让我们回到问题。您不需要使用正则表达式来访问脚本标签的内容。id例如<script id="myId">...</script>,如果添加属性,则可以轻松访问元素。

让我们看一个这样的实现的例子。

const x = `
  <html>
    <script id="myScript">
      alert("this.is.sparta");
      function pClicked() {console.log("p is clicked");}
    </script>
    <body>
      <p onClick="pClicked()">Hello</p>
    </body>
  </html>
`;

const Hello = React.createClass({

  displayName: 'Hello',

  componentDidMount() {
    const script = document.getElementById('myScript').innerHTML;
    window.eval(script);
  }

  render() {
    return <div dangerouslySetInnerHTML={{__html: x}} />;
  }

});
Run Code Online (Sandbox Code Playgroud)

如果您有多个脚本,则可以添加一个数据属性[data-my-script],例如,然后使用jQuery访问它:

const x = `
  <html>
    <script data-my-script="">
      alert("this.is.sparta");
      function pClicked() {console.log("p is clicked");}
    </script>
    <script data-my-script="">
      alert("another script");
    </script>
    <body>
      <p onClick="pClicked()">Hello</p>
    </body>
  </html>
`;

const Hello = React.createClass({

  constructor(props) {
    super(props);

    this.helloElement = null;
  }

  displayName: 'Hello',

  componentDidMount() {
    $(this.helloElement).find('[data-my-script]').each(function forEachScript() {
      const script = $(this).text();
      window.eval(script);
    });
  }

  render() {
    return (
      <div
        ref={helloElement => (this.helloElement = helloElement)} 
        dangerouslySetInnerHTML={{__html: x}} 
      />
    );
  }

});
Run Code Online (Sandbox Code Playgroud)

无论如何,最好避免使用eval,因此另一种选择是获取文本并使用原始脚本内容附加新的script标签,而不是调用eval这个答案暗示了这种方法