window.onload เทียบกับ document.onload


709

สนับสนุนอย่างกว้างขวางมากขึ้น: window.onloadหรือdocument.onload?


2
เอกสาร MDN อธิบายเหล่านี้windowเหตุการณ์: และonload DOMContentLoadedตัวอย่างการใช้งาน:, window.addEventListener('DOMContentLoaded', callback). ราวกลางปี ​​2562 เข้ากันได้กับเบราว์เซอร์หลักทั้งหมด ----- developer.mozilla.org/en-US/docs/Web/API/Window/… ------ developer.mozilla.org/en-US/docs/Web/API/Window/load_event
Craig Hicks

สำหรับผมแม้จะยังคงใน Firefox 75.0 ในวันนี้window.onloadและdocument.onloadมีความแตกต่างจากคนอื่น ๆ ! window.onloadดูเหมือนว่าจะเกิดขึ้นในภายหลังและโหลดอีกเล็กน้อยdocument.onload! (! บางสิ่งบางอย่างกำลังทำงานกับหน้าต่างที่ไม่ได้ทำงานกับเอกสารที่ไปสำหรับ document.onreadstatechange 'สมบูรณ์' เช่นกัน!)
แอนดรู

คำตอบ:


722

พวกเขาจะยิงเมื่อไหร่?

window.onload

  • โดยค่าเริ่มต้นจะทำงานเมื่อโหลดหน้าเว็บทั้งหมดรวมถึงเนื้อหา (รูปภาพ, CSS, สคริปต์ ฯลฯ )

ในบางเบราว์เซอร์ตอนนี้จะเข้ามามีบทบาทdocument.onloadและไฟไหม้เมื่อ DOM พร้อมเช่นกัน

document.onload

  • มันถูกเรียกเมื่อ DOM พร้อมซึ่งสามารถก่อนภาพและเนื้อหาภายนอกอื่น ๆ จะถูกโหลด

รองรับได้ดีแค่ไหน?

window.onloadดูเหมือนจะได้รับการสนับสนุนอย่างกว้างขวางที่สุด ในความเป็นจริงบางส่วนของเบราว์เซอร์ที่ทันสมัยที่สุดมีในความรู้สึกแทนที่ด้วยdocument.onloadwindow.onload

ปัญหาการสนับสนุนเบราว์เซอร์มักเป็นสาเหตุว่าทำไมหลายคนเริ่มใช้ไลบรารีเช่นjQueryเพื่อจัดการการตรวจสอบเอกสารที่มีความพร้อมเช่น:

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

เพื่อจุดประสงค์ของประวัติศาสตร์ window.onloadvs body.onload:

คำถามที่คล้ายกันถูกถามเกี่ยวกับcodingforumsในขณะที่กลับเกี่ยวกับการใช้งานของมากกว่าwindow.onload body.onloadผลลัพธ์ดูเหมือนว่าคุณควรใช้window.onloadเพราะเป็นการดีที่จะแยกโครงสร้างของคุณออกจากการกระทำ


25
อันที่จริงข้อความนั้นดูเหมือนว่าจะนำไปสู่ทางเลือกระหว่างwindow.onloadและ<body onload="">ซึ่งแตกต่างอย่างสิ้นเชิง (และ "โครงสร้างที่แยกต่างหากจากการกระทำ" ทำให้รู้สึกมากขึ้นในบริบทนี้) ไม่ใช่ว่าคำตอบนั้นผิด แต่เป็นพื้นฐานของมัน
Thor84no

2
คำพูดนั้นน่ากลัวในทางไวยากรณ์ ... ไม่ควรให้ความช่วยเหลือในการแก้ไข (ทำเครื่องหมาย) บ้าง?
Kheldar

@ Thor84no ในที่สุดฉันก็พบว่าเวลาที่จะดูนี้อีก ฉันได้ทำการปรับปรุงบางอย่าง
Josh Mein

@ Keldar ฉันตัดสินใจที่จะถอดความพูดเพราะมันค่อนข้างหยาบ
Josh Mein

@JoshMein หมายความว่าdocument.onloadJS เทียบเท่ากับ jQuery document.readyหรือไม่
john cj

276

แนวคิดทั่วไปคือว่าไฟไหม้ window.onloadเมื่อหน้าต่างของเอกสารคือเตรียมตัวให้พร้อมสำหรับการนำเสนอและdocument.onload ไฟไหม้เมื่อต้นไม้ DOM (สร้างจากรหัสที่มาร์กอัปภายในเอกสาร) จะเสร็จสมบูรณ์

จะเป็นการดีที่สมัครรับเหตุการณ์ DOM ต้นไม้ช่วยให้ Offscreen-กิจวัตรผ่าน Javascript ที่เกิดขึ้นเกือบจะไม่มีภาระของ CPU ในทางตรงกันข้ามwindow.onloadอาจใช้เวลาสักครู่ในการเริ่มต้นเมื่อทรัพยากรภายนอกหลายอย่างยังไม่ได้รับการร้องขอแยกวิเคราะห์และโหลด

►สถานการณ์ทดสอบ:

ในการสังเกตความแตกต่างและวิธีที่เบราว์เซอร์ที่คุณเลือกใช้เครื่องมือจัดการเหตุการณ์ดังกล่าวเพียงแค่ใส่รหัสต่อไปนี้ใน<body>แท็ก - - ของเอกสาร

<script language="javascript">
window.tdiff = []; fred = function(a,b){return a-b;};
window.document.onload = function(e){ 
    console.log("document.onload", e, Date.now() ,window.tdiff,  
    (window.tdiff[0] = Date.now()) && window.tdiff.reduce(fred) ); 
}
window.onload = function(e){ 
    console.log("window.onload", e, Date.now() ,window.tdiff, 
    (window.tdiff[1] = Date.now()) && window.tdiff.reduce(fred) ); 
}
</script>

►Result:

นี่คือพฤติกรรมที่เกิดขึ้นซึ่งสามารถมองเห็นได้สำหรับ Chrome v20 (และอาจเป็นเบราว์เซอร์ล่าสุด)

  • ไม่มีdocument.onloadเหตุการณ์
  • onloadไฟไหม้สองครั้งเมื่อประกาศภายใน<body>ครั้งเดียวเมื่อประกาศภายใน<head>(ที่เหตุการณ์นั้นทำหน้าที่เป็นdocument.onload)
  • การนับและการแสดงขึ้นอยู่กับสถานะของตัวนับอนุญาตให้เลียนแบบพฤติกรรมของเหตุการณ์ทั้งสอง
  • หรือประกาศwindow.onloadตัวจัดการเหตุการณ์ภายในขอบเขตของ<head>องค์ประกอบHTML

►ตัวอย่างโครงการ:

รหัสข้างต้นนำมาจากcodebase ของโครงการนี้ ( index.htmlและkeyboarder.js)


สำหรับรายการตัวจัดการเหตุการณ์ของวัตถุหน้าต่างโปรดดูเอกสารประกอบของ MDN


142

เพิ่มฟังเหตุการณ์

<script type="text/javascript">
  document.addEventListener("DOMContentLoaded", function(event) {
      // - Code to execute when all DOM content is loaded. 
      // - including fonts, images, etc.
  });
</script>


Update March 2017

1 JavaScript วานิลลา

window.addEventListener('load', function() {
    console.log('All assets are loaded')
})


2 jQuery

$(window).on('load', function() {
    console.log('All assets are loaded')
})


โชคดี.


14
"เหตุการณ์ DOMContentLoaded ถูกเรียกใช้เมื่อเอกสาร HTML เริ่มต้นถูกโหลดและวิเคราะห์โดยสมบูรณ์โดยไม่ต้องรอสไตล์ชีทรูปภาพและเฟรมย่อยเพื่อให้การโหลดเสร็จสิ้น" - developer.mozilla.org/en/docs/Web/Events/DOMContentLoadedดังนั้นคุณดูเหมือนจะไม่ถูกต้องเกี่ยวกับทุกสิ่งที่ถูกโหลดในกิจกรรมนี้
ProfK

2
@ProfK ขอบคุณสำหรับความคิดเห็นของคุณ คุณลองwindow.addEventListener('load', function() {...})ได้ไหม ฉันได้อัพเดทคำตอบแล้ว
Akash

4
สิ่งที่ฉันชอบเกี่ยวกับคำตอบนี้คือมันให้โซลูชันแบบจาวาสคริปต์ธรรมดา คุณคิดว่าคนส่วนใหญ่คิดว่า jQuery สร้างขึ้นในเบราว์เซอร์ทั้งหมดโดยพิจารณาว่าคำตอบนั้นให้บ่อยแค่ไหน
Dave Land

ปัญหาสองครั้งเมื่อ jquery แช่งใช้เวลาในการโหลดนานเกินไปและคุณไม่ได้รับ $ ฉันเห็นว่า $ (หน้าต่าง). โซลูชันแบบสำเร็จรูปไม่ควรเชื่อถือได้ในการทำงาน
เชน

1
ฉันได้ลองทั้งสองอย่างในโครเมี่ยมวันนี้ มันไม่ได้รอ css และแบบอักษร
movAX13h

78

ตามเอกสารแยก HTML - ปลาย ,

  1. เบราว์เซอร์จะแยกวิเคราะห์ซอร์ส HTML และรันสคริปต์ที่เลื่อนออกไป

  2. A DOMContentLoadedถูกส่งไปdocumentเมื่อ HTML ทั้งหมดได้รับการแยกวิเคราะห์และทำงาน windowเหตุการณ์ฟองไป

  3. เบราว์เซอร์โหลดทรัพยากร (เช่นภาพ) ที่ทำให้การโหลดล่าช้า

  4. เหตุการณ์ที่ถูกส่งไปที่loadwindow

ดังนั้นคำสั่งของการดำเนินการจะเป็น

  1. DOMContentLoadedผู้ฟังเหตุการณ์windowในระยะการจับภาพ
  2. DOMContentLoaded ผู้ฟังเหตุการณ์ของ document
  3. DOMContentLoadedผู้ฟังเหตุการณ์windowในระยะบับเบิล
  4. loadผู้ฟังเหตุการณ์ (รวมถึงonloadตัวจัดการเหตุการณ์) ของwindow

ฟองloadฟังเหตุการณ์ (รวมถึงการonloadจัดการเหตุการณ์) ในdocumentไม่ควรที่จะเรียก เฉพาะloadผู้ฟังที่จับอาจถูกเรียกใช้ แต่เนื่องจากการโหลดของทรัพยากรย่อยเช่นสไตล์ชีทไม่ได้เกิดจากการโหลดเอกสารเอง

window.addEventListener('DOMContentLoaded', function() {
  console.log('window - DOMContentLoaded - capture'); // 1st
}, true);
document.addEventListener('DOMContentLoaded', function() {
  console.log('document - DOMContentLoaded - capture'); // 2nd
}, true);
document.addEventListener('DOMContentLoaded', function() {
  console.log('document - DOMContentLoaded - bubble'); // 2nd
});
window.addEventListener('DOMContentLoaded', function() {
  console.log('window - DOMContentLoaded - bubble'); // 3rd
});

window.addEventListener('load', function() {
  console.log('window - load - capture'); // 4th
}, true);
document.addEventListener('load', function(e) {
  /* Filter out load events not related to the document */
  if(['style','script'].indexOf(e.target.tagName.toLowerCase()) < 0)
    console.log('document - load - capture'); // DOES NOT HAPPEN
}, true);
document.addEventListener('load', function() {
  console.log('document - load - bubble'); // DOES NOT HAPPEN
});
window.addEventListener('load', function() {
  console.log('window - load - bubble'); // 4th
});

window.onload = function() {
  console.log('window - onload'); // 4th
};
document.onload = function() {
  console.log('document - onload'); // DOES NOT HAPPEN
};


ฉันรันข้อมูลโค้ดของคุณและdocument - load - captureเกิดขึ้นจริงซึ่งขัดกับสิ่งที่ฉันคาดหวังในการค้นหาของฉันว่าทำไมการโหลดเอกสารไม่เกิดขึ้นสำหรับฉัน เป็นเรื่องแปลกมาก บางครั้งก็ปรากฏขึ้นบางครั้งก็ไม่ได้บางครั้งก็ปรากฏขึ้นสองครั้ง - แต่ไม่เคยdocument - load - bubbleเกิดขึ้น document loadผมจะแนะนำไม่ได้ใช้
ข้อผิดพลาด

@erroric จุดที่ดี ฉันไม่ได้พิจารณาว่ามีการloadส่งเหตุการณ์ไปยังแหล่งข้อมูลภายนอก เหตุการณ์นั้นไม่ทำให้เกิดฟองดังนั้นจึงมักจะไม่ถูกตรวจพบในเอกสาร แต่ควรอยู่ในช่วงการดักจับ รายการเหล่านี้อ้างถึงการโหลดของ<style>และ<script>องค์ประกอบ ฉันคิดว่า Edge นั้นเหมาะสมสำหรับแสดงและ Firefox และ Chrome นั้นผิด
Oriol

ขอบคุณ Oriol useCaptureตัวเลือกสอนสิ่งใหม่ให้ฉัน
Paul Watson

ขอบคุณสำหรับการสรุปการแยกวิเคราะห์และการเรนเดอร์โฟลว์จาก w3 ฉันเพิ่งสงสัยหลังจากขั้นตอนที่ 4 เมื่อเหตุการณ์ 'โหลด' ถูกไล่ออกมีอะไรอีกที่สามารถเกิดขึ้นได้ ฉันสังเกตเห็นในเบราว์เซอร์ของฉันว่าบางครั้งยังมีวัตถุบางอย่างที่ถูกดึงหลังจากเหตุการณ์โหลดถูกไล่ออกแม้ว่าฉันจะไม่ได้สัมผัสหรือโต้ตอบกับหน้าเว็บเลย คุณรู้หรือไม่ว่าวัตถุเหล่านั้นเรียกว่าอะไร? 'วัตถุเรนเดอร์ที่ไม่บล็อก
weefwefwqg3

12

ใน Chrome window.onload แตกต่างจาก<body onload="">ในขณะที่ทั้งสองจะเหมือนกันทั้ง Firefox (รุ่น 35.0) และ IE (รุ่น 11)

คุณสามารถสำรวจได้โดยตัวอย่างต่อไปนี้:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <!--import css here-->
        <!--import js scripts here-->

        <script language="javascript">

            function bodyOnloadHandler() {
                console.log("body onload");
            }

            window.onload = function(e) {
                console.log("window loaded");
            };
        </script>
    </head>

    <body onload="bodyOnloadHandler()">

        Page contents go here.

    </body>
</html>

และคุณจะเห็นทั้ง "หน้าต่างโหลด" (ซึ่งมาก่อน) และ "body onload" ในคอนโซล Chrome อย่างไรก็ตามคุณจะเห็น "body onload" ใน Firefox และ IE หากคุณเรียกใช้ " window.onload.toString()" ในคอนโซลของ IE & FF คุณจะเห็น:

"function onload (เหตุการณ์) {bodyOnloadHandler ()}"

ซึ่งหมายความว่าการมอบหมาย "window.onload = function (e) ... " ถูกเขียนทับ


6

window.onloadและonunloadเป็นทางลัดไปยังdocument.body.onloadและdocument.body.onunload

document.onload และ onloadตัวจัดการบนแท็ก html ทั้งหมดดูเหมือนว่าจะสงวนไว้ แต่ไม่เคยถูกเรียก

' onload' ในเอกสาร -> จริง


5

window.onload อย่างไรก็ตามพวกเขามักจะเป็นสิ่งเดียวกัน body.onload จะกลายเป็น window.onload ใน IE


1

Window.onload เป็นมาตรฐานอย่างไรก็ตาม - เว็บเบราว์เซอร์ใน PS3 (อ้างอิงจาก Netfront) ไม่รองรับวัตถุหน้าต่างดังนั้นคุณจึงไม่สามารถใช้งานได้


0

ในระยะสั้น

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