Что не эквивалентно jQuery для $ (document) .ready ()?

444

Что является эквивалентом не-jQuery $(document).ready()?

TIMEX
источник
4
Если вы хотите воспроизвести $(document).ready()событие jQuery без использования какой-либо библиотеки, взгляните на это: stackoverflow.com/questions/1795089/…
CMS
@OP: ознакомьтесь со страницей 89 «Техники Pro JavaScript» для реализации ванильного JavaScript $(document).ready()- books.google.com/… . Он также использует addEventабстракцию привязки событий, написанную Дином Эдвардсом, код которого также есть в книге :)
Russ Cam
2
возможный дубликат $ (document). уже эквивалентен без jQuery
Qantas 94 Heavy

Ответы:

73

Хорошая вещь о $(document).ready()том, что он стреляет раньше window.onload. Функция загрузки ожидает загрузки всего, включая внешние ресурсы и изображения. $(document).readyоднако срабатывает, когда дерево DOM завершено и им можно манипулировать. Если вы хотите получить готовый DOM без jQuery, вы можете проверить эту библиотеку. Кто-то извлек только readyчасть из jQuery. Он красивый и маленький, и вы можете найти его полезным:

уже в Google Code

Дуг Нейнер
источник
4
DomReady код сети! через @CMS на github: github.com/cms/domready/network
Kzqai
45
Это не отвечает на вопрос и не показывает никакого кода не jQuery. Как он получил так много голосов?
Даниэль В.
3
@DanielW. Потому что это просто и практично. Большинство из нас пришли сюда в поисках способа убедиться, что DOM готов к использованию в JavaScript-коде.
абаразаль
Да, но некоторые из нас пришли сюда для реального ответа.
Slbox
615

Это отлично работает, от ECMA

document.addEventListener("DOMContentLoaded", function() {
  // code...
});

Он window.onloadне равен JQuery, $(document).readyпоскольку $(document).readyожидает только дерева DOM при window.onloadпроверке всех элементов, включая внешние ресурсы и изображения.

РЕДАКТИРОВАТЬ : Добавлен IE8 и более старый эквивалент, благодаря наблюдению Яна Дерка . Вы можете прочитать исходный код этого кода на MDN по этой ссылке :

// alternative to DOMContentLoaded
document.onreadystatechange = function () {
    if (document.readyState == "interactive") {
        // Initialize your application or run some code.
    }
}

Есть и другие варианты, кроме "interactive". Смотрите MDN ссылку для деталей.

sospedra
источник
Согласиться с Бенджамином. Вы не можете просто использовать attachEvent. Например, в Chrome вы получаете: Uncaught TypeError: document.attachEvent не является функцией. Используйте связанный ответ Яна Дерка.
Мануэль Арвед Шмидт
9
Что если документ уже загружен при вызове этого скрипта? Ничего не случится вообще :(
oriadam
8
@Deerloper Нет, только что попробовал это на консоли Chrome - ничего не произошло: document.addEventListener("DOMContentLoaded",function(){console.log(123)})попробуйте сейчас
oriadam
2
Поддержка DOMContentLoaded в браузерах: caniuse.com/domcontentloaded
Гийом
1
@elliottregan это правда. Я удаляю комментарий, чтобы не загрязнять эту ветку. Я предлагаю всем вам делать то же самое :) И, если нужно, оставьте один комментарий, указывая на комментарий, если это необходимо. Так как это лишнее, потому что оно выходит за рамки вопросов ОК
Соспедра
43

Маленькая вещь, которую я собрал

domready.js

(function(exports, d) {
  function domReady(fn, context) {

    function onReady(event) {
      d.removeEventListener("DOMContentLoaded", onReady);
      fn.call(context || exports, event);
    }

    function onReadyIe(event) {
      if (d.readyState === "complete") {
        d.detachEvent("onreadystatechange", onReadyIe);
        fn.call(context || exports, event);
      }
    }

    d.addEventListener && d.addEventListener("DOMContentLoaded", onReady) ||
    d.attachEvent      && d.attachEvent("onreadystatechange", onReadyIe);
  }

  exports.domReady = domReady;
})(window, document);

Как это использовать

<script src="domready.js"></script>
<script>
  domReady(function(event) {
    alert("dom is ready!");
  });
</script>

Вы также можете изменить контекст, в котором выполняется обратный вызов, передав второй аргумент

function init(event) {
  alert("check the console");
  this.log(event);
}

domReady(init, console);
Спасибо
источник
2
Спасибо. Мне нравится тот факт, что он обратно совместим. Движение вперед не означает просто оставить позади менее удачливых людей. Невозможно использовать современный браузер (по какой-либо причине), к сожалению ...
CO
28

Теперь, когда наступил 2018 год, вот быстрый и простой способ.

Это добавит прослушиватель событий, но если он уже запущен, мы проверим, находится ли dom в состоянии готовности или что он завершен. Это может произойти до или после завершения загрузки подресурсов (изображений, таблиц стилей, фреймов и т. Д.).

function domReady(fn) {
  // If we're early to the party
  document.addEventListener("DOMContentLoaded", fn);
  // If late; I mean on time.
  if (document.readyState === "interactive" || document.readyState === "complete" ) {
    fn();
  }
}

domReady(() => console.log("DOM is ready, come and get it!"));

Дополнительные чтения


Обновить

Вот несколько быстрых утилитарных помощников, использующих стандарт ES6 Import & Export, который я написал, включая также TypeScript. Может быть, я смогу сделать из них быструю библиотеку, которая может быть установлена ​​в проекты как зависимость.

JavaScript

export const domReady = (callBack) => {
  if (document.readyState === "loading") {
    document.addEventListener('DOMContentLoaded', callBack);
  }
  else {
    callBack();
  }
}

export const windowReady = (callBack) => {
  if (document.readyState === 'complete') {
    callBack();
  }
  else {
    window.addEventListener('load', callBack);
  }
}

Машинопись

export const domReady = (callBack: () => void) => {
  if (document.readyState === "loading") {
    document.addEventListener('DOMContentLoaded', callBack);
  }
  else {
    callBack();
  }
}

export const windowReady = (callBack: () => void) => {
  if (document.readyState === 'complete') {
    callBack();
  }
  else {
    window.addEventListener('load', callBack);
  }
}

обещания

export const domReady = new Promise(resolve => {
  if (document.readyState === "loading") {
    document.addEventListener('DOMContentLoaded', resolve);
  }
  else {
    resolve();
  }
});

export const windowReady = new Promise(resolve => {
  if (document.readyState === 'complete') {
    resolve();
  }
  else {
    window.addEventListener('load', resolve);
  }
});
CTS_AE
источник
16

Согласно http://youmightnotneedjquery.com/#ready хорошая замена, которая все еще работает с IE8

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();
    });
  }
}

// test
window.ready(function() {
    alert('it works');
});

Улучшения : Лично я бы также проверил, является ли тип fnфункцией. И как @elliottregan предложил удалить прослушиватель событий после использования.

Причина, по которой я отвечаю на этот вопрос поздно, заключается в том, что я искал этот ответ, но не мог найти его здесь. И я думаю, что это лучшее решение.

онлайн Томас
источник
1
Да, это лучший ответ на мой взгляд. Легко читается, и он выполняет код, даже если DOM уже загружен. Единственное, что я хотел бы добавить, это удалить список событий после запуска события.
elliottregan
14

Существует стандартная замена, DOMContentLoaded, которая поддерживается более чем на 90% браузеров, но не в IE8 (поэтому ниже код, используемый JQuery для поддержки браузеров) :

document.addEventListener("DOMContentLoaded", function(event) { 
  //do work
});

Нативная функция jQuery намного сложнее, чем просто window.onload, как показано ниже.

function bindReady(){
    if ( readyBound ) return;
    readyBound = true;

    // Mozilla, Opera and webkit nightlies currently support this event
    if ( document.addEventListener ) {
        // Use the handy event callback
        document.addEventListener( "DOMContentLoaded", function(){
            document.removeEventListener( "DOMContentLoaded", arguments.callee, false );
            jQuery.ready();
        }, false );

    // If IE event model is used
    } else if ( document.attachEvent ) {
        // ensure firing before onload,
        // maybe late but safe also for iframes
        document.attachEvent("onreadystatechange", function(){
            if ( document.readyState === "complete" ) {
                document.detachEvent( "onreadystatechange", arguments.callee );
                jQuery.ready();
            }
        });

        // If IE and not an iframe
        // continually check to see if the document is ready
        if ( document.documentElement.doScroll && window == window.top ) (function(){
            if ( jQuery.isReady ) return;

            try {
                // If IE is used, use the trick by Diego Perini
                // http://javascript.nwbox.com/IEContentLoaded/
                document.documentElement.doScroll("left");
            } catch( error ) {
                setTimeout( arguments.callee, 0 );
                return;
            }

            // and execute any waiting functions
            jQuery.ready();
        })();
    }

    // A fallback to window.onload, that will always work
    jQuery.event.add( window, "load", jQuery.ready );
}
Zigri2612
источник
1
Новая JQuery прекращена поддержка старых браузеров и теперь они только DOMContentLoadedи loadсобытие , используя addEventListener, и первое , что огнь удалить оба слушатель, так что это не срабатывает два раза.
18:00
8

В простом ванильном JavaScript, без библиотек? Это ошибка. $это просто идентификатор, и он не определен, если вы его не определите.

jQuery определяет $как собственный «все объект» (также известный как jQueryтак, чтобы вы могли использовать его, не конфликтуя с другими библиотеками). Если вы не используете jQuery (или какую-либо другую библиотеку, которая его определяет), то $она не будет определена.

Или вы спрашиваете, что такое эквивалент в простом JavaScript? В этом случае вы, вероятно, хотитеwindow.onload , что не совсем эквивалентно, но это самый быстрый и простой способ приблизиться к тому же эффекту в обычном JavaScript.

Брайан Кэмпбелл
источник
39
Для многих пользователей этого ответа (и других ниже): когда был задан этот вопрос, он просто сказал: «Что такое $ (document) .ready () в javascript? Не jquery. Что это?» Похоже, он спрашивал, что это значит в простом ванильном JavaScript без загруженного jQuery. В своем ответе я попытался ответить на этот вопрос, а также дал самый простой и легкий ответ для простого ванильного JavaScript без jQuery или других библиотек на тот случай, если он это имел в виду. Обратите внимание, что весь дополнительный контекст был добавлен другими людьми, гадающими, о чем спрашивал вопрос, а не оригинальным постером.
Брайан Кэмпбелл,
5

В современных браузерах проще всего было бы использовать соответствующие GlobalEventHandlers , onDOMContentLoaded , onload , onloadeddata (...)

onDOMContentLoaded = (function(){ console.log("DOM ready!") })()

onload = (function(){ console.log("Page fully loaded!") })()

onloadeddata = (function(){ console.log("Data loaded!") })()

Событие DOMContentLoaded наступает, когда исходный HTML-документ полностью загружен и проанализирован, не дожидаясь окончания загрузки таблиц стилей, изображений и подкадров. Совсем другая загрузка событий должна использоваться только для обнаружения полностью загруженной страницы. Это невероятно популярная ошибка - использовать load, когда DOMContentLoaded будет гораздо более уместным, поэтому будьте осторожны.

https://developer.mozilla.org/en-US/docs/Web/Events/DOMContentLoaded

Используемая функция является IIFE, очень полезной в этом случае, так как она запускается сама, когда готова:

https://en.wikipedia.org/wiki/Immediately-invoked_function_expression

Очевидно, более уместно поместить его в конец любого скрипта.

В ES6 мы также можем написать это как функцию стрелки:

onload = (() => { console.log("ES6 page fully loaded!") })()

Лучше всего использовать элементы DOM, мы можем дождаться готовности любой переменной, которая вызывает IIFE со стрелкой.

Поведение будет таким же, но с меньшим воздействием на память.

footer = (() => { console.log("Footer loaded!") })()
<div id="footer">

Во многих случаях объект документа также запускается по готовности , по крайней мере, в моем браузере. Синтаксис тогда очень хорош, но он требует дальнейших проверок на совместимость.

document=(()=>{    /*Ready*/   })()
NVRM
источник
Может ли запуск IIFE до того, как DOM завершит загрузку элементов после него?
CTS_AE
Конечно, это просто функция, анонимная функция, в замыкании.
NVRM
0

Тело onLoad может быть альтернативой:

<html>
<head><title>Body onLoad Exmaple</title>

<script type="text/javascript">
    function window_onload() {
        //do something
    }
</script>

</head>
<body onLoad="window_onload()">

</body>
</html>
joan16v
источник