React: Script tag не работает при вставке с помощью опасноSetInnerHTML

Я пытаюсь установить html, отправленный с моего сервера, чтобы показать внутри div, используя свойство dangerouslySetInnerHTML в React. У меня также есть скриптовый тег внутри него и использовать функции, определенные внутри того же самого внутри html. Я сделал пример ошибки в JSFiddle здесь .

Это тестовый код:

var x = 'alert("this.is.sparta");function pClicked() {console.log("p is clicked");}

Hello

'; var Hello = React.createClass({ displayName: 'Hello', render: function() { return (
); } });

Я проверил, и тег скрипта добавлен в DOM, но не может вызвать функции, определенные в этом теге скрипта. Если это не так, есть другой способ, с помощью которого я могу добавить содержимое тега скрипта.

Вот немного грязного способа сделать это. Немного объясняю, что происходит здесь, вы извлекаете содержимое скрипта через регулярное выражение и только обрабатываете html с помощью реакции, а затем после того, как компонент монтируется, содержимое в теге скрипта выполняется в глобальном масштабе.

 var x = 'alert("this.is.sparta");function pClicked() {console.log("p is clicked");}

Hello

'; var extractscript=/

Я не думаю, что вам нужно использовать конкатенацию ( + ) здесь.

 var x = 'alert("this.is.sparta");function pClicked() {console.log("p is clicked");}

Hello

';

Я думаю, вы можете просто сделать:

 var x = '

Hello

';

Так как это все равно передано опасноSetInnerHTML.

Но вернемся к проблеме. Вам не нужно использовать регулярное выражение для доступа к содержимому тега скрипта. Если вы добавите атрибут id , например , вы можете легко получить доступ к элементу.

Давайте посмотрим пример такой реализации.

 const x = `    

Hello

`; const Hello = React.createClass({ displayName: 'Hello', componentDidMount() { const script = document.getElementById('myScript').innerHTML; window.eval(script); } render() { return
; } });

Если у вас несколько сценариев, вы можете добавить атрибут данных [data-my-script] , а затем получить доступ к нему с помощью jQuery:

 const x = `     

Hello

`; 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 (
(this.helloElement = helloElement)} dangerouslySetInnerHTML={{__html: x}} /> ); } });

В любом случае, всегда полезно избегать использования eval , поэтому другой вариант – получить текст и добавить новый тег скрипта с содержимым скрипта оригинала вместо вызова eval . Этот ответ предполагает такой подход

небольшое расширение для ответа Дасита для будущих просмотров …

У меня была очень похожая проблема, но в моем случае я получил HTML с серверной части, и это заняло некоторое время (часть решения для отчетов, где бэкэнд будет отображать отчет в html)

поэтому то, что я сделал, было очень похоже только на то, что я обработал скрипт, запущенный в функции componentWillMount ():

 import React from 'react'; import jsreport from 'jsreport-browser-client-dist' import logo from './logo.svg'; import './App.css'; class App extends React.Component { constructor() { super() this.state = { report: "", reportScript: "" } } componentWillMount() { jsreport.serverUrl = 'http://localhost:5488'; let reportRequest = {template: {shortid: 'HJH11D83ce'}} // let temp = "this is temp" jsreport.renderAsync(reportRequest) .then(res => { let htmlResponse = res.toString() let extractedScript = / tags since eval expects only code without html tags let scriptLines = scriptToRun.split("\n") scriptLines.pop() scriptLines.shift() let cleanScript = scriptLines.join("\n") console.log('running script ',cleanScript) window.eval(cleanScript) } } } export default App; 

надеюсь, это полезно ...