[javascript] 자바 스크립트 파일을 동적으로로드

JavaScript 파일을 어떻게 안정적으로 동적으로로드 할 수 있습니까? 이것은 ‘초기화’될 때 컴포넌트가 필요한 모든 JavaScript 라이브러리 스크립트를 요청시 동적으로로드하는 모듈 또는 컴포넌트를 구현하는 데 사용될 수 있습니다.

구성 요소를 사용하는 클라이언트는이 구성 요소 <script>를 구현하는 모든 라이브러리 스크립트 파일을로드 하거나 웹 페이지에 수동으로 태그를 삽입 할 필요가 없습니다. 단지 ‘기본’구성 요소 스크립트 파일입니다.

주류 JavaScript 라이브러리는 어떻게 이것을 수행합니까 (시제품, jQuery 등)? 이러한 도구는 여러 JavaScript 파일을 재배포 가능한 단일 ‘빌드’버전의 스크립트 파일로 병합합니까? 아니면 보조 ‘라이브러리’스크립트를 동적으로로드합니까?

이 질문에 추가 : 동적으로 포함 된 JavaScript 파일이로드 된 후 이벤트를 처리하는 방법이 있습니까? 프로토 타입은 document.observe문서 전체 이벤트에 사용됩니다. 예:

document.observe("dom:loaded", function() {
  // initially hide all containers for tab content
  $$('div.tabcontent').invoke('hide');
});

스크립트 요소에 사용 가능한 이벤트는 무엇입니까?



답변

Prototype을 사용하여 동적 스크립트 태그를 작성할 수 있습니다 .

new Element("script", {src: "myBigCodeLibrary.js", type: "text/javascript"});

여기서 문제 는 외부 스크립트 파일이 언제 완전히로드 되는지 알 수 없다는 것 입니다.

우리는 종종 다음 줄에 종속 코드를 원하고 다음과 같이 작성하려고합니다.

if (iNeedSomeMore) {
    Script.load("myBigCodeLibrary.js"); // includes code for myFancyMethod();
    myFancyMethod(); // cool, no need for callbacks!
}

콜백없이 스크립트 종속성을 주입하는 현명한 방법이 있습니다. 동기식 AJAX 요청을 통해 스크립트를 가져 와서 글로벌 수준에서 스크립트를 평가하면됩니다.

프로토 타입을 사용하는 경우 Script.load 메소드는 다음과 같습니다.

var Script = {
    _loadedScripts: [],
    include: function(script) {
        // include script only once
        if (this._loadedScripts.include(script)) {
            return false;
        }
        // request file synchronous
        var code = new Ajax.Request(script, {
            asynchronous: false,
            method: "GET",
            evalJS: false,
            evalJSON: false
        }).transport.responseText;
        // eval code on global level
        if (Prototype.Browser.IE) {
            window.execScript(code);
        } else if (Prototype.Browser.WebKit) {
            $$("head").first().insert(Object.extend(
                new Element("script", {
                    type: "text/javascript"
                }), {
                    text: code
                }
            ));
        } else {
            window.eval(code);
        }
        // remember included script
        this._loadedScripts.push(script);
    }
};


답변

자바 스크립트에는 가져 오기 / 포함 / 요구 사항이 없지만 원하는 것을 달성하는 두 가지 주요 방법이 있습니다.

1-AJAX 호출로로드 한 다음 eval을 사용할 수 있습니다.

이것은 가장 간단한 방법이지만 Javascript 안전 설정으로 인해 도메인으로 제한되며 eval을 사용하면 버그와 해킹의 문이 열립니다.

2-HTML에서 스크립트 URL로 스크립트 태그를 추가하십시오.

확실히 가장 좋은 방법입니다. 외부 서버에서도 스크립트를로드 할 수 있으며 브라우저 파서를 사용하여 코드를 평가할 때 깔끔합니다. 웹 페이지의 헤드 또는 바디의 하단에 태그를 넣을 수 있습니다.

이 두 솔루션 모두 여기에서 설명하고 설명합니다.

이제 알아야 할 큰 문제가 있습니다. 그렇게하면 코드를 원격으로로드 할 수 있습니다. 최신 웹 브라우저는 성능을 향상시키기 위해 모든 것을 비동기식으로로드하기 때문에 파일을로드하고 현재 스크립트를 계속 실행합니다.

즉, 이러한 트릭을 직접 사용하는 경우 새로로드 된 코드를로드 요청 후 다음 줄에서 사용할 수 없습니다.로드가 계속 진행 중이기 때문입니다.

EG : my_lovely_script.js에 MySuperObject가 포함되어 있습니다

var js = document.createElement("script");

js.type = "text/javascript";
js.src = jsFilePath;

document.body.appendChild(js);

var s = new MySuperObject();

Error : MySuperObject is undefined

그런 다음 F5를 치는 페이지를 다시로드하십시오. 그리고 작동합니다! 혼란스러운 …

그래서 어떻게해야합니까?

글쎄, 내가 준 링크에서 저자가 제안한 해킹을 사용할 수 있습니다. 요약하자면, 급한 사람들을 위해, 그는 en 이벤트를 사용하여 스크립트가로드 될 때 콜백 함수를 실행합니다. 따라서 콜백 함수에서 원격 라이브러리를 사용하여 모든 코드를 넣을 수 있습니다. EG :

function loadScript(url, callback)
{
    // adding the script tag to the head as suggested before
   var head = document.getElementsByTagName('head')[0];
   var script = document.createElement('script');
   script.type = 'text/javascript';
   script.src = url;

   // then bind the event to the callback function 
   // there are several events for cross browser compatibility
   script.onreadystatechange = callback;
   script.onload = callback;

   // fire the loading
   head.appendChild(script);
}

그런 다음 스크립트가 람다 함수에로드 된 후 사용하려는 코드를 작성하십시오.

var myPrettyCode = function() {
    // here, do what ever you want
};

그런 다음 모든 것을 실행하십시오.

loadScript("my_lovely_script.js", myPrettyCode);

알았어 그러나이 모든 것을 쓰는 것은 고통입니다.

이 경우 항상 환상적인 무료 jQuery 프레임 워크로 사용할 수 있으므로 한 줄에서 동일한 작업을 수행 할 수 있습니다.

$.getScript("my_lovely_script.js", function() {
    alert("Script loaded and executed.");
    // here you can use anything you defined in the loaded script
});


답변

최근 jQuery 와 함께 훨씬 덜 복잡한 버전을 사용했습니다 .

<script src="scripts/jquery.js"></script>
<script>
  var js = ["scripts/jquery.dimensions.js", "scripts/shadedborder.js", "scripts/jqmodal.js", "scripts/main.js"];
  var $head = $("head");
  for (var i = 0; i < js.length; i++) {
    $head.append("<script src=\"" + js[i] + "\"></scr" + "ipt>");
  }
</script>

IE6 / 7, Firefox, Safari, Opera에서 테스트 한 모든 브라우저에서 훌륭하게 작동했습니다.

업데이트 : jQuery가없는 버전 :

<script>
  var js = ["scripts/jquery.dimensions.js", "scripts/shadedborder.js", "scripts/jqmodal.js", "scripts/main.js"];
  for (var i = 0, l = js.length; i < l; i++) {
    document.getElementsByTagName("head")[0].innerHTML += ("<script src=\"" + js[i] + "\"></scr" + "ipt>");
  }
</script>


답변

나는 기본적으로 당신이 Adam과했던 것과 똑같은 일을했지만, 일을 끝내기 위해 head 태그에 추가되도록 약간 수정했습니다. 스크립트와 CSS 파일을 모두 처리하기 위해 include 함수 (아래 코드)를 만들었습니다.

이 함수는 또한 스크립트 또는 CSS 파일이 이미 동적으로로드되지 않았는지 확인합니다. 수작업으로 코딩 된 값을 확인하지 않으며 더 나은 방법이 있었지만 그 목적을 달성했습니다.

function include( url, type ){
    // First make sure it hasn't been loaded by something else.
    if( Array.contains( includedFile, url ) )
        return;

    // Determine the MIME-type
    var jsExpr = new RegExp( "js$", "i" );
    var cssExpr = new RegExp( "css$", "i" );
    if( type == null )
        if( jsExpr.test( url ) )
            type = 'text/javascript';
        else if( cssExpr.test( url ) )
            type = 'text/css';

    // Create the appropriate element.
    var tag = null;
    switch( type ){
        case 'text/javascript' :
            tag = document.createElement( 'script' );
            tag.type = type;
            tag.src = url;
            break;
        case 'text/css' :
            tag = document.createElement( 'link' );
            tag.rel = 'stylesheet';
            tag.type = type;
            tag.href = url;
            break;
    }

    // Insert it to the <head> and the array to ensure it is not
    // loaded again.
    document.getElementsByTagName("head")[0].appendChild( tag );
    Array.add( includedFile, url );
}


답변

또 다른 멋진 답변

$.getScript("my_lovely_script.js", function(){


   alert("Script loaded and executed.");
  // here you can use anything you defined in the loaded script

 });

https://stackoverflow.com/a/950146/671046


답변

여기 내가 찾은 예제 코드가 있습니다 … 누군가 더 나은 방법이 있습니까?

  function include(url)
  {
    var s = document.createElement("script");
    s.setAttribute("type", "text/javascript");
    s.setAttribute("src", url);
    var nodes = document.getElementsByTagName("*");
    var node = nodes[nodes.length -1].parentNode;
    node.appendChild(s);
  }


답변

jQuery를 이미로드 한 경우 $ .getScript 를 사용해야합니다 .

이것은 (여러 코드가 실행되기 전에 스크립트가로드되도록 보장하기 위해) 내장 된 콜백 함수를 가지고 있으며 캐싱을 제어 할 수 있다는 점에서 다른 답변보다 이점이 있습니다.