web-dev-qa-db-ja.com

動的に読み込まれたJavaScriptブロックをどのように実行しますか?

私はAJAXを呼び出すWebページで作業していますが、次のようなHTMLのチャンクを返します。

<div>
  <!-- some html -->
  <script type="text/javascript">
    /** some javascript */
  </script>
</div>

すべてをDOMに挿入していますが、JavaScriptが実行されていません。それを実行する方法はありますか?

詳細:スクリプトブロックの内容を制御できません(そのため、呼び出し可能な関数に変更できません)。ブロック全体を実行する必要があります。 JavaScriptがHTMLのより大きなブロック内にあるため、応答でevalを呼び出すことができません。なんらかの正規表現を使用してJavaScriptを分離し、それに対してevalを呼び出すこともできますが、それはかなり不幸です。誰かがより良い方法を知っていますか?

38
kristina

要素のinnerHTMLプロパティを設定して追加されたスクリプトは実行されません。新しいdivを作成してinnerHTMLを設定し、この新しいdivをDOMに追加してみてください。例えば:

 <html> 
 <head> 
 <script type = 'text/javascript'> 
 function addScript()
 {
 var str = "<script> alert( 'i am here'); <\/script>"; 
 var newdiv = document.createElement( 'div'); 
 newdiv.innerHTML = str; 
 document.getElementById( 'target')。appendChild(newdiv); 
} 
 </ script> 
 </ head> 
 <body> 
 <input type = "button" value = "add script" onclick = "addScript()" /> 
 <div> hello world </ div> 
 < div id = "target"> </ div> 
 </ body> 
 </ html> 
16
Ed.

Divなどを埋めるために応答を使用している場合、正規表現を使用する必要はありません。 getElementsByTagNameを使用できます。

div.innerHTML = response;
var scripts = div.getElementsByTagName('script');
for (var ix = 0; ix < scripts.length; ix++) {
    eval(scripts[ix].text);
}
16
Scott Nichols

一方、@ Edからの回答は受け入れられました。 Firefoxの現在のバージョンでは動作しませんGoogle Chromeまたは動的に追加されたスクリプトを呼び出すために彼の例をうまく活用できたSafariブラウザ。

必要な変更は、スクリプトがDOMに追加される方法のみです。 innerHTMLとして追加する代わりに、新しいスクリプト要素を作成し、実際のスクリプトコンテンツをinnerHTMLとして作成した要素に追加し、スクリプト要素を実際のターゲットに追加しました。

<html>
<head>
<script type='text/javascript'>
function addScript()
{
    var newdiv = document.createElement('div');

    var p = document.createElement('p');
    p.innerHTML = "Dynamically added text";
    newdiv.appendChild(p);

    var script = document.createElement('script');
    script.innerHTML = "alert('i am here');";
    newdiv.appendChild(script);

    document.getElementById('target').appendChild(newdiv);
}
</script>
</head>
<body>
<input type="button" value="add script" onclick="addScript()"/>
<div>hello world</div>
<div id="target"></div>
</body>
</html>

これは、Firefox 42、Google Chrome 48およびSafari 9.0.3で動作します。

9
Roman Vottner

別の方法は、Ajax呼び出しからの戻り値をInnerHTMLを使用してDOMにダンプするだけではありません。

各ノードを動的に挿入すると、スクリプトが実行されます。

それ以外の場合、ブラウザはテキストノードを挿入していると見なし、スクリプトを無視します。

Evalの使用は、Javascript VMの別のインスタンスを起動し、渡された文字列をJITする必要があるため、かなり邪悪です。

2
FlySwat

最善の方法は、DOMを介してスクリプトブロックのコンテンツを直接識別して評価することでしょう。

ただし、注意が必要です。オフサイトコールの制限を克服するためにこれを実装する場合は、セキュリティホールが開かれます。

実装したものはすべてXSSに悪用される可能性があります。

1

これをネイティブに行う人気のあるAjaxライブラリの1つを使用できます。 プロトタイプ が好きです。 Ajax呼び出しの一部としてevalScripts:trueを追加するだけで、自動的に実行されます。