2009-11-02 2 views
11

기타 관련 콘텐츠를 포함하고 있습니다. 웹 페이지는 <body> 태그의 끝 부분에 <script> 태그를 추가하여 다른 자바 스크립트 파일을로드합니다. 흐름은 약간 복잡한, 그래서 내 질문 요청하기 전에 그것을 설명하려고합니다 : 브라우저가 <body> 요소 동적으로 포함 된 스크립트를 IE에서 두 번로드하는 것을 중지하십시오.

  • 의 src 속성의 끝 부분에서 우리 <script> 요소와 페이지를로드

    • 을 스크립트 태그는 두 번째로 <script> 요소를 삽입하는 자바 스크립트 파일을 가리 킵니다
    • 삽입 된 <script> 요소의 src 특성은 마지막으로 페이지의 해당 부분에 일부 내용을 주입하는 또 다른 자바 스크립트 파일을 가리 킵니다.

    로드하는 데 시간이 오래 걸릴 수있는 최종 콘텐츠를 포함할지 여부를 결정하기 전에 몇 가지 기본 처리를 수행 할 수 있도록이 2 단계 접근 방식을 사용하고 있습니다.

    문제는 IE8 (및 이전 버전)이 마지막 자바 스크립트를 두 번로드한다는 것입니다. src 속성을 설정하면로드가 발생하지만 스크립트 태그를 DOM에 추가하게됩니다. 이것을 피할 수있는 방법이 있습니까?

    문제의 bare-bones demo을 만들었습니다. HTTP 요청을 추적하는 방법이 있다면 IE8이 js_test2.js를 두 번로드한다는 것을 알 수 있습니다.

  • 답변

    15

    루트의 차이 IE 스크립트 요소에게 그것은 부모 요소의 childNodes에 추가됩니다 처음 실행하는 것입니다, 부모 요소가 실제로 문서에 있는지 여부에 관계없이 다른 브라우저는 childNodes의 문서 트리 안의 노드에 추가 될 때만 스크립트를 실행합니다.

    jQuery의 domManip 기능 append 및 기타 유사한 jQuery를 메소드에 의해 호출되고, 영리 시도하고, 최종 해석 된 HTML에서 찾은 <script> 요소 evalScript 호출 (jQuery를 1.3.2의 524 라인)의 실행에 스크립트 (외부 스크립트에 필요한 경우 AJAX 요청을 수행하여). (실제 스크립트 요소는 파싱 된 childNodes에서 제거되어 문서 삽입시 실행되지 않게됩니다. 따라서 스크립트를 포함하는 내용이 여러 요소에 동시에 추가 될 때 스크립트가 한 번만 실행됩니다.)

    그러나 이전의 clean 함수는 HTML을 구문 분석하는 동안 스크립트 요소를 래퍼 div에 추가했기 때문에 IE는 이미 스크립트를 실행했을 것입니다. 그래서 당신은 두 번의 처형을 받게됩니다.

    가장 좋은 방법은 append과 같은 기능을 스크립트를 사용하여 HTML 문자열과 함께 사용하지 않는 것입니다.

    사실, 직렬화 된 HTML 문자열에 내용을 넣고 jQuery로 파싱하는 것을 잊어 버리십시오.

    이 이
    var s= document.createElement('script'); 
    s.type= 'text/javascript'; 
    s.charset= 'UTF-8'; 
    s.src= 'js_test2.js'; 
    document.getElementById('some_container').appendChild(s); 
    
    이 이 이

    이 (솔직히하려면 clean 함수의 위-옵니다 소스 코드를 본 후, 내가 jQuery의 사용에 대한 심각한 의문에 봉착 HTML 문자열을 기반 : 단지 그것을 훨씬 더 신뢰할 수있는 일반 DOM 방법을 . 아무것도 DOM 조작은 전혀 브라우저 버그를 수정하기로했다,하지만 바보 - 정규식 처리는 나에게 그것이 해결 가능한 많은 문제를 일으킬 가능성이 보인다)이 초기 호출에 덧붙여

    :.

    document.write(unescape("%3Cscript src='js_test1.js' type='text/javascript'%3E%3C/script%3E")); 
    

    당신은 유엔을 필요로하지 않습니다. 여기 케이프; 왜 그렇게 많은 사람들이하는지 모르겠다. 시퀀스 </은 인라인 스크립트에서 피할 필요가 있습니다. <script> 태그가 끝나야하고 XHTML을 사용하는 경우 <&은 피해야합니다 (CDATA 래퍼를 사용하는 경우 ]]>). 더 쉬운 방법이 있습니다. 바로 자바 스크립트 문자열 리터럴로 모든 일을 방법 :

    document.write('\x3Cscript src="js_test1.js" type="text/javascript">\x3C/script>")); 
    
    +0

    매우 철저한 대답에 감사드립니다. 나는 더 전통적인 DOM 방식으로 되돌아 왔고, 지금은 잘 작동한다. 초기 호출에서 이스케이프 해제에 관해서 : 올바르게 기억하면 Google 애널리틱스가 스크립트를 포함시키기 위해 사용하는 코드를 복사했습니다. 누군가가 원격 자바 스크립트를 강력하게 포함하는 방법을 알고 있다면 GA 사람들 . 해명 해줘서 고마워. – stiang

    2

    jquery가 XmlHttpRequest를 사용하여 js_test2의 두 번째 인스턴스를 가져 오는 것 같습니다.

    왜 나는 JQuery의 동작을 모르지만 조사해야합니다.

    +0

    을 업데이트,이 문제를 해결해야한다고 생각하지만, 당신이 옳은 것 같다. jQuery append 대신 appendChild를 사용하면 js_test2.js가 두 번로드되지 않습니다. 데모/정말로/베어 - 본즈 (jQuery없이)를 만들었다 고 생각한다면, 나 자신을 발견했을 것이다. 감사! – stiang

    +0

    몇 가지 조사를했습니다. 결과 (아래)는 좋지 않습니다. – bobince

    4

    유사한 상황 (예 : <script> 노드의 복제)에서 다른 버전의 IE에서 이러한 동작이 발생하는 것을 보았습니다. 스크립트 실행을 두 번 중지하는 방법을 알지 못했기 때문에 결국 스크립트 코드가 두 번 실행되지 않도록 보호합니다. 스크립트를 두 번 실행 방지하는 방법을 찾을 수없는 경우, 대신 그 방법을 시도 할 수 있습니다

    if (typeof(loaded) == 'undefined') { 
        // the whole code goes in here 
        var loaded = true; 
    } 
    

    : 그것은 뭔가 같았다.

    +0

    awesome, 스크립트가 실행되기 전에 false를 정의하지 않고 전역 변수가 정의되었는지 확인하는 방법을 찾으려고했습니다. 감사! –

    1

    당신은로드하기 전에 스크립트가 문서에 이미 있는지 확인할 수 있습니다 - 그것을

    function fetchscript(url, callback){ 
    var S= document.getElementsByTagName('script'), L= S.length; 
    while(L){ 
        if(S[--L].src== url) return true; 
    } 
    //create and append script and any callbacks 
    } 
    
    0

    그것은 당신이 <script> 요소에 이미있을 때 당신이 document.write을 사용하기 때문에 이것이 가능성이 있습니다. document.write 대신 <head>에 추가하려고 했습니까?

    1

    동일한 문제가 발생합니다. IE에서만 발생합니다.

    jQuery의 html() 방법 체인은 다음과 같습니다 html>append>domManip>clean

    clean() 방법 IE에서 innerHTMLevalScript 스크립트 태그 끝에 script 태그가 바로로드 버그 (첫 번째로드), jQuery를 가지고 DOM에 innerHTML 메이크업 문자열을 사용 domManip 메서드 (아약스로드). 그리고 나서 스크립트 파일은 IE에서 두 번로드됩니다.

    나는 jQuery를 그냥 기괴한의 깨끗한() 메소드

    관련 문제