Reagire: il tag Script non funziona se inserito usando dangerouslySetInnerHTML

Sto cercando di impostare html inviato dal mio server per mostrare all’interno di un div usando la proprietà pericolosamenteSetInnerHTML in React. Ho anche un tag script all’interno e uso funzioni definite nello stesso all’interno di html. Ho fatto un esempio di errore in JSFiddle qui .

Questo è il codice di prova:

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

Hello

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

Ho controllato e il tag script è stato aggiunto a DOM, ma non è ansible chiamare le funzioni definite all’interno di tale tag script. Se questo non è il modo corretto c’è un altro modo con cui posso iniettare il contenuto del tag dello script.

Ecco un po ‘di sporco modo di farlo, un po’ di spiegazione su cosa sta succedendo qui, si estrae il contenuto dello script tramite un’espressione regolare, e si esegue il rendering html usando react, quindi dopo che il componente è montato il contenuto nel tag script viene eseguito su un ambito globale.

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

Hello

'; var extractscript=/

Non penso che sia necessario utilizzare la concatenazione ( + ) qui.

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

Hello

';

Penso che puoi semplicemente fare:

 var x = '

Hello

';

Dal momento che è passato a dangerouslySetInnerHTML comunque.

Ma torniamo al problema. Non è necessario utilizzare regex per accedere al contenuto del tag dello script. Se si aggiunge l’attributo id , ad esempio , è ansible accedere facilmente all’elemento.

Vediamo un esempio di tale implementazione.

 const x = `    

Hello

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

Se si dispone di più script, è ansible aggiungere un attributo di dati [data-my-script] ad esempio, quindi accedervi utilizzando 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}} /> ); } });

In ogni caso, è sempre consigliabile evitare l’uso di eval , quindi un’altra opzione è quella di ottenere il testo e aggiungere un nuovo tag script al contenuto dello script originale invece di chiamare eval . Questa risposta suggerisce un simile approccio

una piccola estensione per la risposta di Dasith per le viste future …

Ho avuto un problema molto simile ma nel mio caso ho ottenuto l’HTML dal lato server e ci ho messo un po ‘(parte della soluzione di reporting in cui il backend renderizza il report in html)

quindi quello che ho fatto è stato molto simile solo a quello che ho gestito lo script in esecuzione nella funzione 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; 

spero che questo sia utile ...