javascript - 이벤트 - 페이지 로딩 완료 후 스크립트 실행




jQuery의 $.ready()-페이지/DOM이 준비 될 때 함수 호출 방법 (7)

준비된

function ready(fn){var d=document;(d.readyState=='loading')?d.addEventListener('DOMContentLoaded',fn):fn();}

좋아요 사용

ready(function(){
    //some code
});

자체 호출 코드

(function(fn){var d=document;(d.readyState=='loading')?d.addEventListener('DOMContentLoaded',fn):fn();})(function(){

    //Some Code here
    //DOM is avaliable
    //var h1s = document.querySelector("h1");

});

지원 : IE9 +

이 질문에는 이미 답변이 있습니다.

좋아, 이것은 어리석은 질문 일지 모르지만 나는 때때로 다른 사람들이 똑같은 질문을하는 것을 확신한다. 나, 나는 단지 그것에 대해 100 % 확실하게하고 싶다. jQuery를 통해 우리 모두는 훌륭한 것을 알고 있습니다.

$('document').ready(function(){});

그러나 라이브러리를 지원하지 않는 표준 JavaScript로 작성된 함수를 실행하고 페이지를 처리 ​​할 준비가되자 마자 함수를 시작하려고한다고 가정 해 보겠습니다. 이것에 접근하는 적절한 방법은 무엇입니까?

나는 내가 할 수 있음을 안다.

window.onload="myFunction()";

... 또는 body 태그를 사용할 수 있습니다.

<body onload="myFunction()">

... 또는 나는 페이지의 맨 아래에서 모든 것을 끝내고 시도 할 수도 있지만, 최종 body 또는 html 태그는 다음과 같습니다.

<script type="text/javascript">
   myFunction();
</script>

jQuery의 $.ready() 와 같은 방식으로 하나 이상의 함수를 발행하는 크로스 브라우저 (이전 / 신규) 호환 방식이란 무엇입니까?


HubSpot의 훌륭한 사람들은 jQuery의 장점을 많이 달성 할 수있는 순수한 자바 방법론을 찾을 수있는 리소스를 가지고 있습니다.

http://youmightnotneedjquery.com/#ready

function ready(fn) {
  if (document.readyState != 'loading'){
    fn();
  } else if (document.addEventListener) {
    document.addEventListener('DOMContentLoaded', fn);
  } else {
    document.attachEvent('onreadystatechange', function() {
      if (document.readyState != 'loading')
        fn();
    });
  }
}

인라인 사용 예 :

ready(function() { alert('hello'); });

jQuery없이 VANILLA 일반 자바 스크립트 를 사용하는 경우 다음을 사용해야합니다 (Internet Explorer 9 이상).

document.addEventListener("DOMContentLoaded", function(event) {
    // Your code to run since DOM is loaded and ready
});

위의 것은 jQuery에 해당합니다.

$(document).ready(function() {
    console.log("Ready!");
});

어떤 ALSO도 이와 같이 작성할 수 있습니다. jQuery는 준비가 완료된 후에도 실행 occurs .

$(function() {
    console.log("ready!");
});

아래에 동의하지 않아야합니다 (DOM 준비가되어 있지 않음).

자체 실행되는 IIFE 과 같이 사용하지 마십시오.

 Example:

(function() {
   // Your page initialization code here  - WRONG
   // The DOM will be available here   - WRONG
})();

이 IIFE는 DOM이로드 될 때까지 기다리지 않습니다. (저는 최신 버전의 Chrome 브라우저에 대해서도 이야기하고 있습니다!)


귀하의 방법 (닫는 본문 태그 앞에 스크립트를 두는 것)

<script>
   myFunction()
</script>
</body>
</html>

이전 및 새 브라우저를 지원하는 신뢰할 수있는 방법입니다.


모든 크로스 브라우저 호환성을 수행하는 프레임 워크가 없다면 가장 간단한 방법은 코드 끝 부분에 코드를 호출하는 것입니다. 이것은 onload 핸들러보다 실행이 더 빠릅니다. 왜냐하면 모든 이미지가로드되는 것이 아니라 DOM이 준비 될 때까지 기다리기 때문입니다. 그리고, 이것은 모든 브라우저에서 작동합니다.

<html>
<head>
</head>
<body>
Your HTML here

<script>
// self executing function here
(function() {
   // your page initialization code here
   // the DOM will be available here

})();
</script>
</body>
</html>

만약 당신이 정말로 이런 식으로하고 싶지 않고 크로스 브라우저 호환성이 필요하고 window.onload 를 기다리고 싶지 않다면 아마 jQuery와 같은 프레임 워크가 $(document).ready() 구현하는 방법을 살펴 봐야 할 것입니다 $(document).ready() 메소드. 그것은 브라우저의 기능에 따라 상당히 관련되어 있습니다.

jQuery가 어떤 역할을하는지 (스크립트 태그가있는 곳이면 어디서나 작동)

지원되는 경우 표준을 시도합니다.

document.addEventListener('DOMContentLoaded', fn, false);

대체 수단 :

window.addEventListener('load', fn, false )

또는 이전 버전의 IE에서는 다음을 사용합니다.

document.attachEvent("onreadystatechange", fn);

대체 수단 :

window.attachEvent("onload", fn);

그리고 IE 코드 경로에는 내가 따라야 할 몇 가지 해결 방법이 있지만 프레임과 관련이있는 것처럼 보입니다.

여기에 일반 자바 스크립트로 작성된 jQuery의 .ready() 를 완전히 대신 할 수 있습니다.

(function(funcName, baseObj) {
    // The public function name defaults to window.docReady
    // but you can pass in your own object and own function name and those will be used
    // if you want to put them in a different namespace
    funcName = funcName || "docReady";
    baseObj = baseObj || window;
    var readyList = [];
    var readyFired = false;
    var readyEventHandlersInstalled = false;

    // call this when the document is ready
    // this function protects itself against being called more than once
    function ready() {
        if (!readyFired) {
            // this must be set to true before we start calling callbacks
            readyFired = true;
            for (var i = 0; i < readyList.length; i++) {
                // if a callback here happens to add new ready handlers,
                // the docReady() function will see that it already fired
                // and will schedule the callback to run right after
                // this event loop finishes so all handlers will still execute
                // in order and no new ones will be added to the readyList
                // while we are processing the list
                readyList[i].fn.call(window, readyList[i].ctx);
            }
            // allow any closures held by these functions to free
            readyList = [];
        }
    }

    function readyStateChange() {
        if ( document.readyState === "complete" ) {
            ready();
        }
    }

    // This is the one public interface
    // docReady(fn, context);
    // the context argument is optional - if present, it will be passed
    // as an argument to the callback
    baseObj[funcName] = function(callback, context) {
        if (typeof callback !== "function") {
            throw new TypeError("callback for docReady(fn) must be a function");
        }
        // if ready has already fired, then just schedule the callback
        // to fire asynchronously, but right away
        if (readyFired) {
            setTimeout(function() {callback(context);}, 1);
            return;
        } else {
            // add the function and context to the list
            readyList.push({fn: callback, ctx: context});
        }
        // if document already ready to go, schedule the ready function to run
        if (document.readyState === "complete") {
            setTimeout(ready, 1);
        } else if (!readyEventHandlersInstalled) {
            // otherwise if we don't have event handlers installed, install them
            if (document.addEventListener) {
                // first choice is DOMContentLoaded event
                document.addEventListener("DOMContentLoaded", ready, false);
                // backup is window load event
                window.addEventListener("load", ready, false);
            } else {
                // must be IE
                document.attachEvent("onreadystatechange", readyStateChange);
                window.attachEvent("onload", ready);
            }
            readyEventHandlersInstalled = true;
        }
    }
})("docReady", window);

최신 버전의 코드는 GitHub ( https://github.com/jfriend00/docReady 에서 공개적으로 공유됩니다.

용법:

// pass a function reference
docReady(fn);

// use an anonymous function
docReady(function() {
    // code here
});

// pass a function reference and a context
// the context will be passed to the function as the first argument
docReady(fn, context);

// use an anonymous function with a context
docReady(function(context) {
    // code here that can use the context argument that was passed to docReady
}, ctx);

이것은에서 테스트되었습니다 :

IE6 and up
Firefox 3.6 and up
Chrome 14 and up
Safari 5.1 and up
Opera 11.6 and up
Multiple iOS devices
Multiple Android devices

작업 구현 및 테스트 베드 : http://jsfiddle.net/jfriend00/YfD3C/

작동 방식에 대한 요약은 다음과 같습니다.

  1. 비공개 상태 변수를 가질 수 있도록 IIFE (즉시 호출 된 함수 식)를 만듭니다.
  2. 공용 함수 선언하기 docReady(fn, context)
  3. docReady(fn, context) 가 호출되면 준비 처리기가 이미 시작되었는지 확인합니다. 그렇다면 setTimeout(fn, 1) 하여이 JS 스레드가 끝난 직후 새로 추가 된 콜백을 시작하도록 예약하십시오.
  4. 준비된 핸들러가 아직 시작되지 않은 경우 나중에 호출 할 콜백 목록에이 새 콜백을 추가하십시오.
  5. 문서가 이미 준비되어 있는지 확인하십시오. 그렇다면 모든 준비 핸들러를 실행하십시오.
  6. 문서가 언제 준비되는지 알기 위해 이벤트 리스너를 설치하지 않은 경우 지금 설치하십시오.
  7. document.addEventListener 가있는 경우 "DOMContentLoaded""load" 이벤트에 대해 .addEventListener() 를 사용하여 이벤트 핸들러를 설치하십시오. "로드"는 안전을위한 백업 이벤트이므로 필요하지 않아야합니다.
  8. document.addEventListener 가 없으면 "onreadystatechange""onload" 이벤트에 대해 .attachEvent() 를 사용하여 이벤트 처리기를 설치하십시오.
  9. onreadystatechange 이벤트에서 document.readyState === "complete" 인지 확인하고, 그렇다면 준비된 모든 핸들러를 시작하는 함수를 호출하십시오.
  10. 다른 모든 이벤트 핸들러에서 모든 준비 핸들러를 시작하는 함수를 호출하십시오.
  11. 준비된 모든 핸들러를 호출하는 함수에서 상태 변수를 검사하여 이미 해고되었는지 확인하십시오. 우리가 가진다면 아무것도하지 마라. 아직 호출되지 않았다면 준비 함수 배열을 반복하고 각 함수를 추가 된 순서대로 호출합니다. 이것들이 모두 불려 갔다 있도록 (듯이) 플래그를 설정해, 한 번 이상 실행되지 않게합니다.
  12. 함수 배열을 지우면 사용중인 모든 클로저를 해제 할 수 있습니다.

docReady() 로 등록 된 핸들러는 등록 된 순서대로 실행되도록 보장됩니다.

문서가 이미 준비된 후에 docReady(fn) 를 호출하면 setTimeout(fn, 1) 사용하여 현재 실행 스레드가 완료 되 자마자 콜백이 실행되도록 예약됩니다. 이렇게하면 호출 코드는 JS의 현재 스레드가 완료되고 호출 순서가 유지되는 즉시 나중에 호출되는 비동기 콜백이라고 항상 간주 할 수 있습니다.


정리 된 비 평가 버전의 Ram-swaroop's "모든 브라우저에서 작동하는"다양한 버전이 있습니다. 모든 브라우저에서 작동합니다!

function onReady(yourMethod) {
  var readyStateCheckInterval = setInterval(function() {
    if (document && document.readyState === 'complete') { // Or 'interactive'
      clearInterval(readyStateCheckInterval);
      yourMethod();
    }
  }, 10);
}
// use like
onReady(function() { alert('hello'); } );

그러나 실행에 추가 10 밀리 초가 걸리지 않으므로 다음과 같이하면 안됩니다.

function onReady(yourMethod) {
  if (document.readyState === 'complete') { // Or also compare to 'interactive'
    setTimeout(yourMethod, 1); // Schedule to run immediately
  }
  else {
    readyStateCheckInterval = setInterval(function() {
      if (document.readyState === 'complete') { // Or also compare to 'interactive'
        clearInterval(readyStateCheckInterval);
        yourMethod();
      }
    }, 10);
  }
}

// Use like
onReady(function() { alert('hello'); } );

// Or
onReady(functionName);

프레임 워크없이 DOM이 준비되었는지 확인하는 방법 도 참고하십시오 . .


모든 브라우저에서 작동 하는 순수한 자바 스크립트 트릭 과 함께 가능한 몇 가지 가능한 방법에 대해 말씀 드리고자 합니다 .

// with jQuery 
$(document).ready(function(){ /* ... */ });

// shorter jQuery version 
$(function(){ /* ... */ });

// without jQuery (doesn't work in older IEs)
document.addEventListener('DOMContentLoaded', function(){ 
    // your code goes here
}, false);

// and here's the trick (works everywhere)
function r(f){/in/.test(document.readyState)?setTimeout('r('+f+')',9):f()}
// use like
r(function(){
    alert('DOM Ready!');
});

원래 작성자가 설명한 것처럼 여기서 트릭은 document.readyState 속성을 확인하는 것입니다. 문자열 in 문자열이 포함되어 있으면 ( uninitialized 에서 loading 중, 처음 두 개의 DOM 준비 상태 가 5에서 제외됨) 타임 아웃을 설정하고 다시 확인합니다. 그렇지 않으면 전달 된 함수를 실행합니다.

그리고 여기 모든 브라우저에서 작동 하는 트릭을위한 jsFiddle있습니다.

Tutorialzine 에게 감사의 말을 Tutorialzine .





html