Статьи

Совет: замените jQuery’s Ready () на простой JavaScript

Эта статья была рецензирована Мев-Раэлем и Тимом Севериеном . Спасибо всем рецензентам SitePoint за то, что сделали контент SitePoint как можно лучше!

ready метод был реализован в jQuery для выполнения кода, когда DOM полностью загружен. Так как она выполняет данную функцию, когда все элементы DOM доступны, вы можете быть уверены, что попытка получить доступ или манипулировать элементами будет работать.

До jQuery 3.0 типичное использование с анонимной функцией выглядело так:

 $(document).ready(function() { // Handler for .ready() called. }); 

Изменения в jQuery 3.0 ready ()

До выхода версии 3 было несколько способов вызвать ready метод:

  • на элементе документа: $(document).ready(handler);
  • для пустого элемента: $().ready(handler);
  • или напрямую (т.е. не на конкретном элементе): $(handler);

Все вышеперечисленные варианты являются функционально эквивалентными. Указанный обработчик будет вызван, когда DOM будет полностью загружен, независимо от того, к какому элементу он был вызван. Другими словами, вызов его для элемента изображения $("img") сравнению с элементом документа не означает, что обратный вызов запускается при загрузке указанного элемента. Вместо этого он будет вызван, когда весь DOM будет полностью загружен.

В jQuery 3.0 все другие синтаксические методы, кроме $(handler); устарели. Официальное обоснование:

Это связано с тем, что выбор не имеет отношения к поведению метода .ready() , который неэффективен и может привести к неверным предположениям о поведении метода.

Разница между событиями готовности и загрузки

Событие ready запускается, когда DOM полностью загружен и доступ к элементам безопасен. Событие load , с другой стороны, запускается после загрузки DOM и всех ресурсов.

Событие загрузки можно использовать следующим образом:

 $(window).on("load", function(){ // Handler when all assets (including images) are loaded }); 

Это ожидает не только готовности DOM к взаимодействию, но и полной загрузки изображений (что может занять время, в зависимости от размеров изображения).

Для обычных манипуляций с DOM вам, вероятно, не понадобится событие load , но это может быть правильным выбором, если вы хотите показать спиннер загрузки, например, до тех пор, пока все ресурсы не будут загружены, или если вы хотите выполнить некоторые вычисления с размерами изображения.

Вам, вероятно, не нужен jQuery.ready ()

Метод ready обеспечивает выполнение кода только тогда, когда все элементы DOM безопасны для манипулирования. Но что это значит? Когда вы выполняете код JavaScript внутри раздела <head> HTML-документа, это обеспечит выполнение кода, когда браузер загрузит также все следующие элементы (например, элемент <body> ):

 <!doctype html> <html> <head> <meta charset="utf-8"> <title>.ready() tutorial</title> <script src="https://cdn.jsdelivr.net/jquery/latest/jquery.min.js"></script> <script> $(function(){ // .ready() callback, is only executed when the DOM is fully loaded var length = $("p").length; // The following will log 1 to the console, as the paragraph exists. // This is the evidence that this method is only called when the // DOM is fully loaded console.log(length); }); </script> </head> <body> <p>I'm the content of this website</p> </body> </html> 

Если вы выполняете JavaScript как последнюю вещь внутри <body> , вам, вероятно, не нужно заключать его в ready() , поскольку все элементы, которыми вы можете пытаться манипулировать или обращаться к ним, уже загружены:

 <!doctype html> <html> <head> <meta charset="utf-8"> <title>.ready() tutorial</title> </head> <body> <p>I'm the content of this website</p> <script src="https://cdn.jsdelivr.net/jquery/latest/jquery.min.js"></script> <script> var length = $("p").length; // The following will log 1 to the console, as the paragraph exists. console.log(length); </script> </body> </html> 

Простой JavaScript готов () Альтернатива

Для современных браузеров и IE9 + вы можете прослушивать событие DOMContentLoaded :

 document.addEventListener("DOMContentLoaded", function(){ // Handler when the DOM is fully loaded }); 

Но обратите внимание, что обратный вызов не будет выполнен, если событие уже сработало. Чтобы убедиться, что обратный вызов всегда выполняется, jQuery проверяет состояние readyState документа ( ссылка ) и, если он уже complete , немедленно выполняет обратный вызов:

 var callback = function(){ // Handler when the DOM is fully loaded }; if ( document.readyState === "complete" || (document.readyState !== "loading" && !document.documentElement.doScroll) ) { callback(); } else { document.addEventListener("DOMContentLoaded", callback); } 

Вы также можете включить библиотеку domReady , в которой уже реализовано это решение.

Старые версии Internet Explorer

Для версий IE меньше или равных 8, вы можете использовать событие onreadystatechange для обнаружения readyState документа:

 document.attachEvent("onreadystatechange", function(){ // check if the DOM is fully loaded if(document.readyState === "complete"){ // remove the listener, to make sure it isn't fired in future document.detachEvent("onreadystatechange", arguments.callee); // The actual handler... } }); 

В качестве альтернативы вы можете использовать событие загрузки, как это делает jQuery, так как это будет работать в любом браузере. Это также приводит к задержке, так как будет ожидать загрузки всех ресурсов. Обратите внимание, что вам также необходимо проверить readyState в этом решении, как описано выше, чтобы убедиться, что обратный вызов будет по-прежнему выполняться, даже если событие уже сработало.

Вывод

Если вы ищете простую альтернативу JavaScript для ready метода, вы можете перейти к событию DOMContentLoaded . Если ваши системные требования включают IE <9, вы можете использовать событие onreadystatechange .

Если вы используете в своем проекте jQuery, вы можете безопасно использовать встроенную функцию ready, но не забывайте избегать использования (устаревшего ready() метода ready() для элементов (например, $(document).ready() ), как уже упоминалось. ранее.

И, наконец, не забывайте, что во многих ситуациях вам может не понадобиться ни одно из этих решений – просто переместите свой JavaScript перед закрывающим </body> и вы можете быть уверены, что DOM завершил загрузку!