Javascript - Як визначити, чи завантажений документ (IE 7 / Firefox 3)


163

Я хочу викликати функцію після завантаження документа, але документ може бути або ще не закінченим завантаженням. Якщо це все-таки завантажилося, я можу просто зателефонувати у функцію. Якщо він НЕ завантажився, я можу приєднати слухача події. Я не можу додати eventlistener після того, як onload вже запущено, оскільки він не буде викликаний. Тож як я можу перевірити, чи документ завантажений? Я спробував код нижче, але він не працює повністю. Будь-які ідеї?

var body = document.getElementsByTagName('BODY')[0];
// CONDITION DOES NOT WORK
if (body && body.readyState == 'loaded') {
    DoStuffFunction();
} else {
    // CODE BELOW WORKS
    if (window.addEventListener) {  
        window.addEventListener('load', DoStuffFunction, false);
    } else {
        window.attachEvent('onload', DoStuffFunction);
    }
}

5
Msgstr "Я хочу викликати функцію після завантаження документа, але документ може ще не закінчитися завантаженням." Це не обчислює.
Річард Сімейс

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

Відповіді:


257

Немає необхідності в усіх кодах, згаданих галамбалазами. Перехресний браузерний спосіб зробити це в чистому JavaScript - просто перевірити document.readyState:

if (document.readyState === "complete") { init(); }

Це також, як це робить jQuery.

Залежно від того, де завантажений JavaScript, це можна зробити через інтервал:

var readyStateCheckInterval = setInterval(function() {
    if (document.readyState === "complete") {
        clearInterval(readyStateCheckInterval);
        init();
    }
}, 10);

Насправді document.readyStateможе бути три стани:

Повертає "завантаження" під час завантаження документа, "інтерактивне", як тільки він закінчує розбір, але все ще завантажує підресурси, і "завершує" після його завантаження. - document.readyState в Мережі розробників Mozilla

Тож якщо вам потрібен лише DOM, щоб бути готовим, перевірте document.readyState === "interactive". Якщо вам потрібна вся сторінка, щоб бути готовою, включаючи зображення, перевірте document.readyState === "complete".


3
@costa, якщо document.readyState == "complete"це означає, що завантажено все, включаючи зображення.
Лоран

Я використовую комбінацію обох подій і document.readyStateпереконуюсь, що функція починається після розбору DOM або пізніше, залежно від того, коли вона була викликана. Чи є подія для інтерактивних readyState ?
Томаш Зато - Відновіть Моніку

3
Я б користувався /loaded|complete/.test(document.readyState). Деякі браузери встановлено document.readyStateна "завантажено", а не "завершено". Крім того, document.readyState НЕ забезпечує завантаження шрифтів, немає реального хорошого способу перевірити це без плагіна.
Райан Тейлор

2
Про що document.onreadystatechange? Це здається більш спрощеним, якщо браузери його підтримують. stackoverflow.com/questions/807878 / ...

2
Я думаю, що було б краще перевірити document.readyState !== "loading"стан "DOM готовий". Це запобігає вирішенню проблем, якщо readyStateпозначка перевіряється із запізненням з якоїсь причини (після "інтерактивного" стану).
rnevius

32

Немає потреби в бібліотеці. jQuery деякий час використовував цей сценарій, btw.

http://dean.edwards.name/weblog/2006/06/again/

// Dean Edwards/Matthias Miller/John Resig

function init() {
  // quit if this function has already been called
  if (arguments.callee.done) return;

  // flag this function so we don't do the same thing twice
  arguments.callee.done = true;

  // kill the timer
  if (_timer) clearInterval(_timer);

  // do stuff
};

/* for Mozilla/Opera9 */
if (document.addEventListener) {
  document.addEventListener("DOMContentLoaded", init, false);
}

/* for Internet Explorer */
/*@cc_on @*/
/*@if (@_win32)
  document.write("<script id=__ie_onload defer src=javascript:void(0)><\/script>");
  var script = document.getElementById("__ie_onload");
  script.onreadystatechange = function() {
    if (this.readyState == "complete") {
      init(); // call the onload handler
    }
  };
/*@end @*/

/* for Safari */
if (/WebKit/i.test(navigator.userAgent)) { // sniff
  var _timer = setInterval(function() {
    if (/loaded|complete/.test(document.readyState)) {
      init(); // call the onload handler
    }
  }, 10);
}

/* for other browsers */
window.onload = init;

1
Саме те, що я шукав - функція jQuery.ready без бібліотеки jQuery. Дякую!
stricjux

3
Повністю пропустив суть питання. initне запуститься, якщо цей код, який ви опублікували, включений після того, як сторінка вже завантажена, в чому полягає пункт ОП: він / вона не може контролювати, коли його сценарій включений. (зауважте, що працюватиме лише setIntervalфілія)
Roatin Marth

3
Це належить до бібліотеки. Поряд з усіма іншими колесами люди зазвичай переосмислюють.
b01

14

Можливо, ви хочете використовувати щось на зразок jQuery, що полегшує програмування JS.

Щось на зразок:

$(document).ready(function(){
   // Your code here
});

Здавалося б, робиш те, що ти шукаєш.


2
І якщо він хоче побачити, як jQuery робить це портативно, джерело jQuery є для перевірки :-)
Thomas L Holaday,

7
І якщо це не ясно, якщо ready()викликається після завантаження документа, передана функція запускається негайно.
Бен Бланк

2
@Ben Blank: якщо, звичайно, не включений сам jQuery після завантаження документа;)
Roatin Marth

@Roatin Marth - Насправді це теж добре працює. (Щойно спробував це з jQuery 1.7.1 на FF8 та IE8.)
Бен Бланк

35
-1: навіть якщо відповідь має сенс, ОП ніколи не згадував jQuery. Використання всього проекту jQuery лише для того, щоб підготувати документ - це шлях надмірності.
marcgg

8
if(document.readyState === 'complete') {
    DoStuffFunction();
} else {
    if (window.addEventListener) {  
        window.addEventListener('load', DoStuffFunction, false);
    } else {
        window.attachEvent('onload', DoStuffFunction);
    }
}

Схоже, робота в останньому Chrome document.loadedзавжди не визначена
Анікет

це був 2010 рік :). Зараз я буду користуватисяbody.readyState === 'loaded'
Jman

6

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

Включити в JavaScript javascript (тобто завжди викликається перед завантаженням):

var pageisloaded=0;
window.addEvent('load',function(){
 pageisloaded=1;
});

Тоді ваш код:

if (pageisloaded) {
 DoStuffFunction();
} else {
 window.addEvent('load',DoStuffFunction);
}

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

Можливо, є кращий спосіб, але я ще його не знайду.


4

Mozila Firefox каже, що onreadystatechangeце альтернатива DOMContentLoaded.

// alternative to DOMContentLoaded
document.onreadystatechange = function () {
    if (document.readyState == "complete") {
        initApplication();
    }
}

У DOMContentLoadedдокументі Mozila в документі сказано:

Подія DOMContentLoaded запускається, коли документ повністю завантажений та проаналізований, не чекаючи закінчення завантаження таблиць стилів, зображень та підкадрів (подія завантаження може використовуватися для виявлення повністю завантаженої сторінки).

Я думаю, що loadподія має бути використана для повного завантаження документа +.


3

Наведене вище з JQuery - це найпростіший і в основному використовується спосіб. Однак ви можете використовувати чистий javascript, але спробуйте визначити цей сценарій у голові, щоб він читався на початку. Що ви шукаєте - це window.onloadподія.

Нижче представлений простий сценарій, який я створив для запуску лічильника. Потім лічильник зупиняється після 10 ітерацій

window.onload=function()
{
    var counter = 0;
    var interval1 = setInterval(function()
    { 
        document.getElementById("div1").textContent=counter;
        counter++; 
        if(counter==10)
        {
            clearInterval(interval1);
        }
    },1000);

}

2

Спробуйте це:

var body = document.getElementsByTagName('BODY')[0];
// CONDITION DOES NOT WORK
if ((body && body.readyState == 'loaded') || (body &&  body.readyState == 'complete') ) {
    DoStuffFunction();
} else {
    // CODE BELOW WORKS
    if (window.addEventListener) {
        window.addEventListener('load', DoStuffFunction, false);
    } else {
        window.attachEvent('onload',DoStuffFunction);
    }
}

1

У мене є інше рішення, мою програму потрібно запустити, коли буде створений новий об’єкт MyApp, щоб він виглядав так:

function MyApp(objId){
     this.init=function(){
        //.........
     }
     this.run=function(){
          if(!document || !document.body || !window[objId]){
              window.setTimeout(objId+".run();",100);
              return;
          }
          this.init();
     };
     this.run();
}
//and i am starting it 
var app=new MyApp('app');

він працює на всіх браузерах, що я знаю.

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