AJAX 호출 후 innerHTML에 의해 주입 된 <script> 실행


100

"Content"라는 div가 있습니다.

<div id="content"></div>

<script>태그를 포함하여 AJAX에 의해 PHP 파일의 데이터로 채워 져야합니다 . 그러나이 태그 내의 스크립트는 실행되지 않습니다.

<div id="content"><!-- After AJAX loads the stuff that goes here -->
   <script type="text/javascript">
     //code
   </script>
   <!-- More stuff that DOES work here -->
</div>

div를 어떻게로드하고 있습니까? 사용하는 라이브러리에 따라 다르지만 일반적으로 ajax로드 후에 스크립트를 실행할지 여부를 제어 할 수 있습니다.
Bill Yang

1
스크립트를 포함하여 div의 내용을 포함하는 다른 (php) 페이지를 요청 window.onload하는 XMTHttpRequest객체를 만든 후 . 나는 평범한 JS로 이것을하고있다. (내 자신의 lol 이외의 라이브러리는 없다)
JCOC611

답변:


65

DOM 텍스트로 삽입 된 JavaScript는 실행되지 않습니다. 그러나 동적 스크립트 패턴 을 사용하여 목표를 달성 할 수 있습니다 . 기본 아이디어는 실행할 스크립트를 외부 파일로 이동하고 Ajax 응답을받을 때 스크립트 태그를 만드는 것입니다. 그런 다음 src스크립트 태그 및 짜잔 의 속성 을 설정 하면 외부 스크립트를로드하고 실행합니다.

이 다른 StackOverflow 게시물도 도움이 될 수 있습니다. 스크립트를 innerHTML로 삽입 할 수 있습니까? .


로드 된 모든 스크립트를 선택하고 eval () 함수로 실행할 수 있습니다.$('#audit-view script').each(function (index, element) { eval(element.innerHTML); })
Jerzy Gebler

페이지에 추가 된 자바 스크립트는 반드시 실행되어야합니다. ( 예 : jsfiddle.net/wnn5fz3m/1 ). 문제는 왜 가끔 그렇지 않습니까?
NoBugs 2015 년

@Chocula 나는 내 스크립트를 별도의 파일로 옮겼지만 여전히 부분적으로 작동하지 않습니다. stackoverflow.com/questions/42941856/...
삼라

참고로 (@NoBugs가 단서를 제공합니다). 나는 일반 javascirpt element.innerHTML = zzz 및 desnt 작업을 시도했습니다. 그런 다음 Jquery $ (element) .html (zzz) 시도하고 작동했습니다.
gtryonp

66

이 코드를 사용했는데 잘 작동합니다.

var arr = MyDiv.getElementsByTagName('script')
for (var n = 0; n < arr.length; n++)
    eval(arr[n].innerHTML)//run script inside div

4
저에게 물어 보면 이것은 받아 들여진 대답보다 훨씬 더 나은 대답입니다. 이것은 거의 JavaScript 주입입니다.
Xedret 2013 년

유용하지만 스크립트 실행 되지 않는 이유에 대한 질문에는 실제로 답변하지 않습니다 . 예를 들어 jsfiddle.net/fkqmcaz7jsfiddle.net/wnn5fz3m/1을 참조하십시오. 절대적으로 실행되어야하며 작동하지 않는 간단한 경우를 찾지 못했습니다.
NoBugs 2015

1
@NaoiseGolden OP는 말 그대로 스크립트 실행에 대해 묻고 있으므로 여기서 괜찮다고 생각합니다. :-)
thedayturns

1
Eval ()은 적극 권장하지 않습니다. -이 참조 stackoverflow.com/questions/9107847/...
킹스

15

다음과 같이 Ajax를 통해 div 내에서 스크립트 블록을로드하는 경우 :

<div id="content">
    <script type="text/javascript">
    function myFunction() {
      //do something
    }
    myFunction();
    </script>
</div>

... 페이지의 DOM을 업데이트하기 만하면 myFunction ()이 반드시 호출되는 것은 아닙니다.

jQuery의 ajax () 메서드에 있는 것과 같은 Ajax 콜백 메서드를 사용하여 요청이 완료 될 때 실행할 항목을 정의 할 수 있습니다.

당신이하는 일은 처음부터 자바 스크립트가 포함 된 페이지를 로딩하는 것과는 다릅니다 (실행되는).

일부 콘텐츠를 가져온 후 성공 콜백 및 오류 콜백을 사용하는 방법의 예 :

  $.ajax({
    type: 'GET',
    url: 'response.php',
    timeout: 2000,
    success: function(data) {
      $("#content").html(data);
      myFunction();
    },
    error: function (XMLHttpRequest, textStatus, errorThrown) {
      alert("error retrieving content");
    }

또 다른 빠르고 더러운 방법은 jQuery 또는 기타 라이브러리를 사용하지 않으려는 경우 eval () 을 사용 하여 DOM 텍스트로 삽입 한 스크립트 코드를 실행하는 것입니다.


jQuery의 콜백을 사용하여 새 <script> 내부의 코드를 어떻게 "실행"할 수 있습니까?
JCOC611 2011 년

성공 콜백을 사용하는 예를 추가했습니다.
Christopher Tokar 2011 년

1
정말 고맙습니다! "myFunction ();" 부분은 내가 내 코드에서 제외하고 있던 것입니다.
Jason

11

다음은 텍스트의 모든 스크립트 태그를 평가하는 스크립트입니다.

function evalJSFromHtml(html) {
  var newElement = document.createElement('div');
  newElement.innerHTML = html;

  var scripts = newElement.getElementsByTagName("script");
  for (var i = 0; i < scripts.length; ++i) {
    var script = scripts[i];
    eval(script.innerHTML);
  }
}

서버에서 HTML을받은 후에이 함수를 호출하십시오. 경고 : 사용 eval은 위험 할 수 있습니다.

데모 : http://plnkr.co/edit/LA7OPkRfAtgOhwcAnLrl?p=preview


5

이것은 문서에 XHR 반환 HTML의 하위 집합을 추가하지 않는 경우 jQuery를 사용하여 '그냥 작동합니다'. ( jQuery의 문제를 보여주는 이 버그 보고서 를 참조하십시오 .)

다음은 작동을 보여주는 예입니다.

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> 
<html lang="en"> 
<head> 
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> 
    <title>test_1.4</title> 
    <script type="text/javascript" charset="utf-8" src="jquery.1.4.2.js"></script> 
    <script type="text/javascript" charset="utf-8"> 
        var snippet = "<div><span id='a'>JS did not run<\/span><script type='text/javascript'>" +
        "$('#a').html('Hooray! JS ran!');" +
        "<\/script><\/div>";
        $(function(){
            $('#replaceable').replaceWith($(snippet));
        });
    </script> 
</head> 
<body> 
    <div id="replaceable">I'm going away.</div> 
</body> 
</html>

위의 내용은 다음과 같습니다. http://jsfiddle.net/2CTLH/


1
이것은 정말 오래된 jQuery 버전의 버그이기 때문에 현재 문제에 대한 해결책이 될 가능성은 거의 없습니다.
NoBugs 2015

3

다음은 AJAX 응답을 구문 분석하는 데 사용할 수있는 함수입니다. 특히 minifiedjs를 사용하고 반환 된 Javascript를 실행하거나 DOM에 추가하지 않고 스크립트를 구문 분석하려는 경우 예외 오류도 처리합니다. 이 코드를 php4sack 라이브러리에서 사용했으며 라이브러리 외부에서 유용합니다.

function parseScript(_source) {
    var source = _source;
    var scripts = new Array();

    // Strip out tags
    while(source.toLowerCase().indexOf("<script") > -1 || source.toLowerCase().indexOf("</script") > -1) {
        var s = source.toLowerCase().indexOf("<script");
        var s_e = source.indexOf(">", s);
        var e = source.toLowerCase().indexOf("</script", s);
        var e_e = source.indexOf(">", e);

        // Add to scripts array
        scripts.push(source.substring(s_e+1, e));
        // Strip from source
        source = source.substring(0, s) + source.substring(e_e+1);
    }

    // Loop through every script collected and eval it
    for(var i=0; i<scripts.length; i++) {
        try {
          if (scripts[i] != '')
          {         
            try  {          //IE
                  execScript(scripts[i]);   
      }
      catch(ex)           //Firefox
      {
        window.eval(scripts[i]);
      }   

            }  
        }
        catch(e) {
            // do what you want here when a script fails
         // window.alert('Script failed to run - '+scripts[i]);
          if (e instanceof SyntaxError) console.log (e.message+' - '+scripts[i]);
                    }
    }
// Return the cleaned source
    return source;
 }

2

스크립트 태그가 필요한 것을 주입하는 경우 잡히지 않은 구문 오류가 발생하고 불법 토큰이라고 말할 수 있습니다. 이를 방지하려면 닫는 스크립트 태그에서 슬래시를 이스케이프해야합니다. 즉;

var output += '<\/script>';

양식 태그와 같은 닫는 태그도 마찬가지입니다.


0

여기에 비슷한 게시물이 있습니다. jquery없이 ajax로드에 addEventListener로드

내가 해결 한 방법은 내 stateChange 함수 내에 함수 호출을 삽입하는 것이 었습니다. 내가 설정 한 페이지는 3 개의 다른 페이지를 contentArea에로드하는 3 개의 버튼이었습니다. 페이지 1, 2 또는 3을로드하기 위해 어떤 버튼을 눌렀는지 알아야했기 때문에 if / else 문을 사용하여로드되는 페이지와 실행할 기능을 쉽게 결정할 수있었습니다. 내가하려는 것은 요소 ID로 인해 특정 페이지가로드 될 때만 작동하는 다른 버튼 리스너를 등록하는 것입니다 ..

그래서...

(page1이로드 중이면 pageload = 1) registerListeners1 함수 실행

2 페이지 또는 3 페이지도 동일합니다.


0

이것은 ajax .done의 각 스크립트 내용에 대해 eval을 호출하여 저에게 효과적이었습니다.

$.ajax({}).done(function (data) {      
    $('div#content script').each(function (index, element) { eval(element.innerHTML); 
})  

참고 : ajax에 따라 조정해야하는 $ .ajax에 매개 변수를 작성하지 않았습니다.


0

내 결론은 HTML이 NESTED SCRIPT 태그를 허용하지 않는다는 것입니다. 내부에 스크립트 태그를 포함하는 HTML 코드를 삽입하기 위해 javascript를 사용하는 경우 javascript도 스크립트 태그에 들어가기 때문에 작동하지 않습니다. 다음 코드로 테스트 할 수 있으며 작동하지 않을 것입니다. 사용 사례는 AJAX 또는 이와 유사한 서비스를 호출하고 HTML을 가져오고 HTML DOM에 직접 삽입하려는 경우입니다. 삽입 된 HTML 코드에 SCRIPT 태그가 있으면 작동하지 않습니다.

<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"></head><body></body><script>document.getElementsByTagName("body")[0].innerHTML = "<script>console.log('hi there')</script>\n<div>hello world</div>\n"</script></html>

-3

또 다른 방법은 다음과 같은 스크립트로 페이지를로드하는 것입니다.

<div id="content" onmouseover='myFunction();$(this).prop( 'onmouseover', null );'>
<script type="text/javascript">
function myFunction() {
  //do something
}
myFunction();
</script>
</div>

그러면 페이지가로드 된 다음 스크립트가 실행되고 함수가 실행되면 이벤트 핸들러가 제거됩니다. 이것은 ajax로드 직후에 실행되지 않지만 사용자가 div 요소를 입력 할 때까지 기다리는 경우 제대로 작동합니다.

추신. Jquery 필요

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.