Що таке не-jQuery еквівалент '$ (документ) .ready ()'?


444

Що таке еквівалент не jQuery $(document).ready()?


4
Якщо ви хочете відтворити $(document).ready()подію jQuery, не використовуючи жодної бібліотеки, подивіться на це: stackoverflow.com/questions/1795089/…
CMS

@OP: перегляньте сторінку 89 Техніки Pro JavaScript для реалізації ванільного JavaScript $(document).ready()- books.google.com/… . Він також використовує addEventабстракцію подій, обов'язкове для написання Діна Едвардса, код якого також є у книзі :)
Russ Cam

Відповіді:


73

Приємне в тому $(document).ready(), що він стріляє раніше window.onload. Функція навантаження чекає, поки все буде завантажено, включаючи зовнішні активи та зображення. $(document).readyоднак, спрацьовує, коли дерево DOM завершено і ним можна керувати. Якщо ви хочете отримати DOM готовий, без jQuery, ви можете зайти в цю бібліотеку. Хтось витягнув лише readyчастину з jQuery. Його приємно і мало, і вам це може бути корисним:

domready в коді Google


4
Кодова мережа DomReady! через @CMS в github: github.com/cms/domready/network
Kzqai

45
Це не відповідає на запитання, а також не містить жодного коду, який не jQuery. Як воно отримало стільки оновлень?
Даніель В.

3
@DanielW. Тому що це просто і практично. Більшість із нас приїхали сюди, шукаючи спосіб переконатися, що DOM готовий до використання кодом JavaScript.
абаразал

Так, але деякі з нас приїхали сюди для фактичної відповіді.
Slbox

614

Це чудово працює від ECMA

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

window.onloadЧи не збігається з JQuery , $(document).readyтому що $(document).readyчекає тільки до дерева DOM , а window.onloadперевірити всі елементи , включаючи зовнішні активи і зображення.

EDIT : Додано IE8 та старший еквівалент, завдяки спостереженню Яна Дерка . Ви можете прочитати джерело цього коду на MDN за цим посиланням :

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

Крім інших варіантів "interactive". Докладніше див . Посилання MDN .


Домовившись з Бенджаміном. Ви не можете просто використовувати attachEvent. Наприклад, у Chrome ви отримуєте: Uncaught TypeError: document.attachEvent не є функцією. Використовуйте пов’язану відповідь Яна Дерка.
Мануель Арвед Шмідт

9
Що робити, якщо документ уже завантажений при виклику цього сценарію?
Зовсім

8
@Deerloper Nope, просто спробував це на консолі Chrome - нічого не сталося: document.addEventListener("DOMContentLoaded",function(){console.log(123)})спробуйте зараз
oriadam

2
Підтримка DOMContentLoaded у браузерах: caniuse.com/domcontentloaded
Гійом Хуста

1
@elliottregan це правда, я видаляю коментар, щоб уникнути забруднення цієї теми, я пропоную вам зробити те саме :) І дозвольте одному коментарю, якщо потрібно, вказавши коментар, якщо це потрібно. Оскільки це додатково, оскільки воно виходить за рамки питань OC
sospedra

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 рік, ось швидкий і простий метод.

Це додасть слухача події, але якщо він вже запущений, ми перевіримо, чи знаходиться домівка в готовому стані або чи завершена. Це може спрацювати до або після завантаження підресурсів (зображення, таблиці стилів, кадри тощо).

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

TypeScript

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

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 вже завантажений. Єдине, що я хотів би додати, - це видалити eventlistener після запуску події.
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 );
}

1
Нова JQuery припинена підтримка старих браузерів і тепер вони тільки DOMContentLoadedі loadподія , використовуючи addEventListener, і перше , що вогонь видалити обидва слухач, так що це не спрацьовує два рази.
jcubic

8

У простому ванільному JavaScript, без бібліотек? Це помилка.$просто ідентифікатор і не визначений, якщо ви не визначите його.

jQuery визначає $як власний "все об'єкт" (також відомий як, jQueryщоб ви могли використовувати його без конфлікту з іншими бібліотеками). Якщо ви не використовуєте jQuery (або якусь іншу бібліотеку, яка його визначає), вона $не буде визначена.

Або ви запитуєте, який еквівалент є у звичайному JavaScript? У цьому випадку ви, мабуть, хочете window.onload, що не зовсім рівнозначно, але це найшвидший і найпростіший спосіб наблизитися до того ж ефекту у ванільному JavaScript.


39
Для багатьох відповідників цієї відповіді (та інших нижче): коли це питання було задано, він сказав просто: "Що таке $ (документ). Вже () в 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 повністю завантажений та проаналізований, не чекаючи завантаження таблиць стилів, зображень та підкадрів. Зовсім інше завантаження подій слід використовувати лише для виявлення повністю завантаженої сторінки. Неймовірно популярна помилка використовувати навантаження, де 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*/   })()

Чи може тригер 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>
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.