jQuery의 Ready 함수 작동 방식에 대한 심층 분석(작동 원리)_jquery

WBOY
풀어 주다: 2016-05-16 15:25:20
원래의
1494명이 탐색했습니다.

이 글에서는 jQuery의 Ready 함수가 어떻게 작동하는지에 대한 심층 분석을 제공합니다. 참고하실 수 있도록 모든 사람과 공유하세요. 자세한 내용은 다음과 같습니다.

jQuery는 훌륭한 스크립팅 라이브러리이며 첫 번째 버전은 2006년 1월 BarCamp NYC에서 John Resig에 의해 출시되었습니다. 최신 버전은 http://jquery.com/에서 다운로드할 수 있습니다. 이 글이 게시된 시점에서 jQuery 버전 2.1.4로 업데이트되었습니다. 여기서는 jQuery1.8.3을 예로 들어 보겠습니다.

jQuery를 배우는 방법은 다양합니다. 오늘은 jQuery의 Ready 함수부터 시작하겠습니다. 이 예제의 코드는 jQuery 스크립트 라이브러리에서 가져온 것입니다.

jQuery를 사용하셨다면 페이지가 준비되었을 때 실행할 수 있는 함수를 등록하는 데 사용되는 준비 함수를 사용하셨을 것입니다.

문제는 우리 페이지가 언제 준비되느냐는 것입니다.

1. 온로드 이벤트

가장 기본적인 처리 방법은 페이지의 onload 이벤트입니다. 이 이벤트를 처리할 때 HTML을 통해 body 요소의 시작 태그에 직접 작성하는 방법이 있습니다. 사용하는 이벤트 등록 방법으로 DOM0 방식과 DOM2 방식으로 나눌 수 있습니다. 브라우저 호환성을 고려하여 아래와 같이 DOM2 모드로 작성합니다.

if (document.addEventListener) {
  // A fallback to window.onload, that will always work
  window.addEventListener("load", jQuery.ready, false);
  // If IE event model is used
} else {
  // A fallback to window.onload, that will always work
  window.attachEvent("onload", jQuery.ready);
}

로그인 후 복사

2. DOMContentLoaded 이벤트

그러나 onload 이벤트는 페이지의 이미지 등을 포함한 모든 페이지 요소가 로드될 때까지 트리거되지 않습니다. 웹페이지에 사진이 많으면 그 효과를 짐작할 수 있습니다. 현재로서는 페이지가 초기화되지 않았고 이벤트도 등록되지 않은 상태입니다. . 너무 늦지 않았나요?

DOM의 onload 이벤트와 유사한 잘 알려진 onload 이벤트 외에도 고려해야 할 DOMContentLoaded 이벤트가 있습니다. 이 이벤트는 모든 DOM이 구문 분석될 때 트리거됩니다. .

이런 방식으로 표준 기반 브라우저의 경우 이 이벤트 처리를 등록할 수도 있습니다. 이러한 방식으로 로딩 완료 이벤트를 더 일찍 포착할 수 있습니다.

if (document.addEventListener) {
  // Use the handy event callback
  document.addEventListener("DOMContentLoaded", DOMContentLoaded, false);
  // A fallback to window.onload, that will always work
  window.addEventListener("load", jQuery.ready, false);
}

로그인 후 복사

3. onreadystatechange 이벤트

비표준 브라우저는 어떻게 해야 하나요?

브라우저에 document.onreadystatechange 이벤트가 있는 경우 이벤트가 발생하면 document.readyState=complete이면 DOM 트리가 로드된 것으로 간주할 수 있습니다.

그러나 이 이벤트는 그다지 안정적이지 않습니다. 예를 들어 페이지에 이미지가 있는 경우 onload 이벤트가 끝날 때까지 트리거되지 않을 수 있습니다. 즉, 페이지에 바이너리가 없는 경우에만 올바르게 실행될 수 있습니다. 리소스가 매우 적거나 캐시됩니다.

if (document.addEventListener) {
  // Use the handy event callback
  document.addEventListener("DOMContentLoaded", DOMContentLoaded, false);
  // A fallback to window.onload, that will always work
  window.addEventListener("load", jQuery.ready, false);
  // If IE event model is used
} else {
  // Ensure firing before onload, maybe late but safe also for iframes
  document.attachEvent("onreadystatechange", DOMContentLoaded);
  // A fallback to window.onload, that will always work
  window.attachEvent("onload", jQuery.ready);
}

로그인 후 복사

DOMContentLoaded 함수는 무엇을 합니까? 마지막으로 jQuery.ready 함수를 호출해야 합니다.

DOMContentLoaded = function() {
  if ( document.addEventListener ) {
    document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false );
    jQuery.ready();
  } else if ( document.readyState === "complete" ) {
    // we're here because readyState === "complete" in oldIE
    // which is good enough for us to call the dom ready!
    document.detachEvent( "onreadystatechange", DOMContentLoaded );
    jQuery.ready();
  }
}

로그인 후 복사

4. doScroll 감지 방법

MSDN에는 JScript 메서드에 대한 눈에 띄지 않는 말이 있습니다. 페이지 DOM이 로드되지 않은 경우 doScroll 메서드가 호출될 때 예외가 생성됩니다. 그런 다음 이를 역으로 사용합니다. 예외가 없으면 페이지 DOM이 로드된 것입니다.

2007년 Diego Perini는 doScroll 메서드 호출을 사용하여 IE가 로드되었는지 확인하는 방법을 보고했습니다. 자세한 지침은 여기에서 확인할 수 있습니다.
원칙은 IE가 iframe이 아닌 곳에 있을 때 doScroll을 실행할 수 있는지 여부에 의해서만 DOM이 로드되었는지 지속적으로 판단할 수 있다는 것입니다. 이 예에서는 50밀리초마다 doScroll을 실행해 봅니다. 페이지가 로드되지 않을 때 doScroll을 호출하면 예외가 발생하므로 try -catch를 사용하여 예외를 포착합니다.

(function doScrollCheck() {
  if (!jQuery.isReady) {
    try {
      // Use the trick by Diego Perini
      // http://javascript.nwbox.com/IEContentLoaded/
      top.doScroll("left");
    } catch (e) {
      return setTimeout(doScrollCheck, 50);
    }
    // and execute any waiting functions
    jQuery.ready();
  }
})();

로그인 후 복사

5. document.readyState 状态

如果我们注册 ready 函数的时间点太晚了,页面已经加载完成之后,我们才注册自己的 ready 函数,那就用不着上面的层层检查了,直接看看当前页面的 readyState 就可以了,如果已经是 complete ,那就可以直接执行我们准备注册的 ready 函数了。不过 ChrisS 报告了一个很特别的错误情况,我们需要延迟一下执行。

setTimeout 经常被用来做网页上的定时器,允许为它指定一个毫秒数作为间隔执行的时间。当被启动的程序需要在非常短的时间内运行,我们就会给她指定一个很小的时间数,或者需要马上执行的话,我们甚至把这个毫秒数设置为0,但事实上,setTimeout有一个最小执行时间,当指定的时间小于该时间时,浏览器会用最小允许的时间作为setTimeout的时间间隔,也就是说即使我们把setTimeout的毫秒数设置为0,被调用的程序也没有马上启动。

这个最小的时间间隔是多少呢?这和浏览器及操作系统有关。在John Resig的新书《Javascript忍者的秘密》一书中提到

Browsers all have a 10ms minimum delay on OSX and a(approximately) 15ms delay on Windows.(在苹果机上的最小时间间隔是10毫秒,在Windows系统上的最小时间间隔大约是15毫秒),另外,MDC中关于setTimeout的介绍中也提到,Firefox中定义的最小时间间隔(DOM_MIN_TIMEOUT_VALUE)是10毫秒,HTML5定义的最小时间间隔是4毫秒。既然规范都是这样写的,那看来使用setTimeout是没办法再把这个最小时间间隔缩短了。

这样,通过设置为 1, 我们可以让程序在浏览器支持的最小时间间隔之后执行了。

// Catch cases where $(document).ready() is called after the browser event has already occurred.
// we once tried to use readyState "interactive" here, but it caused issues like the one
// discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15
if (document.readyState === "complete") {
  // 延迟 1 毫秒之后,执行 ready 函数
  setTimeout(jQuery.ready, 1);
}

로그인 후 복사

6. 完整的代码

在 jQuery 中完整的代码如下所示。位于 jQuery 1.8.3 源代码的 #842 行。

jQuery.ready.promise = function( obj ) {
  if ( !readyList ) {
    readyList = jQuery.Deferred();
    // Catch cases where $(document).ready() is called after the browser event has already occurred.
    // we once tried to use readyState "interactive" here, but it caused issues like the one
    // discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15
    if ( document.readyState === "complete" ) {
      // Handle it asynchronously to allow scripts the opportunity to delay ready
      setTimeout( jQuery.ready, 1 );
    // Standards-based browsers support DOMContentLoaded
    } else if ( document.addEventListener ) {
      // Use the handy event callback
      document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false );
      // A fallback to window.onload, that will always work
      window.addEventListener( "load", jQuery.ready, false );
    // If IE event model is used
    } else {
      // Ensure firing before onload, maybe late but safe also for iframes
      document.attachEvent( "onreadystatechange", DOMContentLoaded );
      // A fallback to window.onload, that will always work
      window.attachEvent( "onload", jQuery.ready );
      // If IE and not a frame
      // continually check to see if the document is ready
      var top = false;
      try {
        top = window.frameElement == null && document.documentElement;
      } catch(e) {}
      if ( top && top.doScroll ) {
        (function doScrollCheck() {
          if ( !jQuery.isReady ) {
            try {
              // Use the trick by Diego Perini
              // http://javascript.nwbox.com/IEContentLoaded/
              top.doScroll("left");
            } catch(e) {
              return setTimeout( doScrollCheck, 50 );
            }
            // and execute any waiting functions
            jQuery.ready();
          }
        })();
      }
    }
  }
  return readyList.promise( obj );
};

로그인 후 복사

那么,又是谁来调用呢?当然是需要的时候,在我们调用 ready 函数的时候,才需要注册这些判断页面是否完全加载的处理,这段代码在 1.8.3 中位于代码的 #244 行,如下所示:

ready: function( fn ) {
  // Add the callback
  jQuery.ready.promise().done( fn );
  return this;
}

로그인 후 복사

在页面上引用 jQuery 脚本库之后,执行了 jQuery 的初始化函数,初始化函数中创建了 ready 函数。我们在通过 ready 函数注册事件处理之前,jQuery 完成了页面检测代码的注册。这样。当页面完全加载之后,我们注册的函数就被调用了。

补充:jquery ready 简写模式

Jquery ready 函数:

$(document).ready(function(){
  alert(' i am ready');
}
);
로그인 후 복사

可简写为:

$(function(){
  alert("i am in");
}
);
로그인 후 복사

希望本文所述对大家jQuery程序设计有所帮助。

관련 라벨:
원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
최신 이슈
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿