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
"ฉันต้องการเรียกใช้ฟังก์ชันหลังจากโหลดเอกสารแล้ว แต่เอกสารนั้นอาจโหลดเสร็จหรือยังไม่เสร็จ" สิ่งนี้ไม่ได้คำนวณ
ริชาร์ดSimões

7
ฉันเชื่อว่าเขาหมายความว่าเขาไม่สามารถควบคุมได้เมื่อมีการเรียกใช้บล็อกโค้ดในตอนแรก แต่ต้องการให้แน่ใจว่าไม่ได้เรียกใช้ DoStuffFunction () ก่อนที่เอกสารจะโหลดเสร็จ
Ben Blank

คำตอบ:


257

ไม่จำเป็นต้องมีรหัสทั้งหมดที่กล่าวถึงโดย galambalazs วิธีการข้ามเบราว์เซอร์ใน 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 Developer Network

ดังนั้นถ้าคุณจะต้อง DOM document.readyState === "interactive"จะมีความพร้อมให้ตรวจสอบ document.readyState === "complete"หากคุณต้องการทั้งหน้าจะมีความพร้อมรวมถึงภาพให้ตรวจสอบ


3
@Costa ถ้าdocument.readyState == "complete"มันหมายถึงทุกอย่างรวมถึงภาพที่ได้รับการโหลด
เรน

ฉันใช้การรวมกันของทั้งสองเหตุการณ์และdocument.readyStateเพื่อให้แน่ใจว่าฟังก์ชั่นเริ่มต้นหลังจาก DOM ได้รับการแยกวิเคราะห์หรือใหม่กว่าขึ้นอยู่กับเมื่อมันถูกเรียก มีเหตุการณ์สำหรับการโต้ตอบ readyStateหรือไม่
Tomáš Zato - Reinstate Monica

3
/loaded|complete/.test(document.readyState)ฉันต้องการใช้ เบราว์เซอร์บางตัวตั้งค่าdocument.readyStateเป็น "โหลด" แทนที่จะเป็น "สมบูรณ์" นอกจากนี้ document.readyState ไม่แน่ใจว่าได้โหลดแบบอักษรแล้วไม่มีวิธีที่ดีในการทดสอบโดยไม่ใช้ปลั๊กอิน
Ryan Taylor

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 Thanx!
stricjux

3
พลาดประเด็นไปอย่างสิ้นเชิง initจะไม่ทำงานหากรหัสนี้ที่คุณโพสต์นั้นถูกรวมไว้หลังจากหน้าโหลดไปแล้วซึ่งเป็นจุดของ OP: เขา / เธอไม่สามารถควบคุมได้เมื่อสคริปต์ของเขารวมอยู่ด้วย (โปรดทราบว่าเฉพาะsetIntervalสาขาเท่านั้นที่สามารถใช้งานได้)
Roatin Marth

3
สิ่งนี้อยู่ในห้องสมุด พร้อมกับล้ออื่น ๆ ที่คนทั่วไปมักจะคิดค้นใหม่
b01

14

คุณอาจต้องการใช้ jQuery ซึ่งทำให้การเขียนโปรแกรม JS ง่ายขึ้น

สิ่งที่ต้องการ:

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

ดูเหมือนจะทำในสิ่งที่คุณเป็น


2
และถ้าเขาต้องการที่จะดูว่า jQuery ไม่ได้ในทางแบบพกพาที่มาของ jQuery จะมีสำหรับการตรวจสอบ :-)
โทมัส L Holaday

7
และในกรณีที่ไม่ชัดเจนหากready()ถูกเรียกหลังจากโหลดเอกสารฟังก์ชันที่ส่งผ่านจะรันทันที
Ben Blank

2
ที่ว่างเปล่า @ Ben: เว้นแต่ของหลักสูตร jQuery ตัวเองรวมอยู่หลังจากที่เอกสารที่มีการโหลด;)
Roatin Marth

@Roatin Marth - ที่จริงแล้วก็ใช้ได้ดีเช่นกัน (ลองใช้กับ jQuery 1.7.1 บน FF8 และ IE8)
Ben Blank

35
-1: แม้ว่าคำตอบจะสมเหตุสมผล OP ไม่เคยกล่าวถึง 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ไม่ได้กำหนดเสมอ
Aniket

นี่คือปี 2010 :) ตอนนี้ฉันจะใช้body.readyState === 'loaded'
Jman

6

หากคุณต้องการให้โค้ดนี้ทำงานขณะโหลดไม่ใช่ที่ domready (เช่นคุณต้องโหลดรูปภาพด้วย) น่าเสียดายที่ฟังก์ชั่นที่พร้อมใช้งานไม่เหมาะกับคุณ ฉันมักจะทำอะไรแบบนี้:

รวมอยู่ในเอกสารจาวาสคริปต์ (เช่นถูกเรียกเสมอก่อนที่จะโหลด onload):

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

จากนั้นรหัสของคุณ:

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

(หรือเทียบเท่าในกรอบการตั้งค่าของคุณ) ฉันใช้รหัสนี้ในการทำจาวาสคริปต์และรูปภาพสำหรับหน้าในอนาคต เนื่องจากสิ่งที่ฉันไม่ได้ใช้สำหรับหน้านี้เลยฉันไม่ต้องการให้มีความสำคัญเหนือกว่าการดาวน์โหลดรูปภาพที่รวดเร็ว

อาจมีวิธีที่ดีกว่านี้ แต่ฉันยังหามันไม่เจอ


4

Mozila Firefox บอกว่าเป็นทางเลือกonreadystatechangeDOMContentLoaded

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

ในDOMContentLoadedเอกสารของ Mozila กล่าวว่า:

เหตุการณ์ DOMContentLoaded ถูกเรียกใช้เมื่อเอกสารได้รับการโหลดและวิเคราะห์อย่างสมบูรณ์โดยไม่ต้องรอสไตล์ชีตรูปภาพและเฟรมย่อยจนเสร็จสิ้นการโหลด (เหตุการณ์โหลดสามารถใช้เพื่อตรวจจับหน้าที่โหลดเต็ม)

ฉันคิดว่าloadควรใช้เหตุการณ์สำหรับการโหลดเอกสาร + แหล่งข้อมูลแบบเต็ม


3

วิธีการข้างต้นกับ JQuery เป็นวิธีที่ง่ายที่สุด อย่างไรก็ตามคุณสามารถใช้จาวาสคริปต์ที่แท้จริง แต่พยายามกำหนดสคริปต์นี้ไว้ในส่วนหัวเพื่อให้อ่านได้ตั้งแต่ต้น สิ่งที่คุณกำลังมองหาคือ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');

มันทำงานบนเบราว์เซอร์ทั้งหมดที่ฉันรู้

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.