it-swarm-ko.tech

동적으로로드 된 JavaScript 블록을 어떻게 실행합니까?

나는 다음과 같은 HTML 덩어리를 반환하는 AJAX 호출하는 웹 페이지에서 일하고 있습니다.

<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> 
 <입력 유형 = "button"value = "add 스크립트"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

대안은 InnerHTML을 사용하여 Ajax 호출에서 DOM으로 리턴을 덤프하지 않는 것입니다.

각 노드를 동적으로 삽입하면 스크립트가 실행됩니다.

그렇지 않으면 브라우저는 텍스트 노드를 삽입한다고 가정하고 스크립트를 무시합니다.

Eval을 사용하는 것은 Javascript VM의 다른 인스턴스를 실행하고 전달 된 문자열을 JIT해야하기 때문에) 다소 악의적입니다.

2
FlySwat

가장 좋은 방법은 아마도 스크립트 블록의 내용을 DOM을 통해 직접 확인하고 평가하는 것입니다.

하지만 조심해야 할 것입니다. 오프 사이트 호출의 한계를 극복하기 위해 이것을 구현하는 경우 보안 허점이 생깁니다.

XSS를 위해 구현 한 것이 무엇이든 이용할 수 있습니다.

1
Quintin Robinson

기본적으로이 작업을 수행하는 인기있는 Ajax 라이브러리 중 하나를 사용할 수 있습니다. 시제품 을 좋아합니다. Ajax 호출의 일부로 evalScripts : true를 추가하면 자동으로 발생합니다.