อะไรที่เทียบเท่า jQuery ของ '$ (เอกสาร) .ready ()'?


444

non-jQuery เทียบเท่า$(document).ready()คืออะไร?


4
หากคุณต้องการที่จะทำซ้ำ$(document).ready()เหตุการณ์ของ jQuery โดยไม่ต้องใช้ห้องสมุดใด ๆ ให้ดูที่: stackoverflow.com/questions/1795089/…
CMS

@OP: ตรวจสอบหน้า 89 เทคนิค JavaScript Pro สำหรับการดำเนินงานของวานิลลา JavaScript $(document).ready()- books.google.com/... นอกจากนี้ยังใช้การaddEventเชื่อมโยงเหตุการณ์ที่เป็นนามธรรมซึ่งเขียนโดย Dean Edwards ซึ่งเป็นรหัสที่อยู่ในหนังสือด้วยเช่นกัน :)
Russ Cam

คำตอบ:


73

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

domready ที่ Google Code


4
เครือข่ายรหัสชั่วร้าย! ผ่าน @CMS บน github: github.com/cms/domready/network
Kzqai

45
สิ่งนี้ไม่ตอบคำถามหรือแสดงรหัสที่ไม่ใช่ jQuery มันได้อย่างไร upvotes มากมาย?
แดเนียลดับเบิลยู.

3
@DanielW เพราะมันง่ายและใช้งานได้จริง พวกเราส่วนใหญ่มาที่นี่เพื่อหาวิธีที่จะทำให้แน่ใจว่า DOM พร้อมใช้งานโดยรหัสจาวาสคริปต์
abarazal

ใช่ แต่พวกเราบางคนมาที่นี่เพื่อรับคำตอบจริง
Slbox

614

มันทำงานได้อย่างสมบูรณ์แบบจาก ECMA

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

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

แก้ไข : เพิ่ม IE8 และเทียบเท่าที่เก่ากว่าขอบคุณการสังเกตของJan Derk คุณสามารถอ่านซอร์สของรหัสนี้บน 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 ไม่ใช่ฟังก์ชัน ใช้คำตอบที่เชื่อมโยงโดย Jan Derk
Manuel Arwed Schmidt

9
เกิดอะไรขึ้นถ้าเอกสารถูกโหลดแล้วเมื่อสคริปต์นี้ถูกเรียก? จะไม่มีอะไรเกิดขึ้นเลย :(
oriadam

8
@Deerloper Nope เพิ่งลองใช้บนคอนโซล Chrome - ไม่มีอะไรเกิดขึ้น: document.addEventListener("DOMContentLoaded",function(){console.log(123)})ลองเลย
oriadam

2
การสนับสนุนDOMContentLoadedในเบราว์เซอร์: caniuse.com/domcontentloaded
Guillaume

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 ฉันเขียนที่มี 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);
  }
});

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แนะนำให้ลบ listener เหตุการณ์หลังการใช้งาน

เหตุผลที่ฉันตอบคำถามนี้ล่าช้าเนื่องจากฉันค้นหาคำตอบนี้ แต่หาไม่พบที่นี่ และฉันคิดว่านี่เป็นทางออกที่ดีที่สุด


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

ใน vanilla JavaScript ธรรมดาไม่มีไลบรารี่? มันเป็นข้อผิดพลาด$เป็นเพียงตัวระบุและไม่ได้กำหนดเว้นแต่คุณจะกำหนดไว้

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

หรือคุณกำลังถามสิ่งที่เทียบเท่าใน JavaScript ธรรมดา? ในกรณีนี้คุณอาจต้องการwindow.onloadซึ่งไม่เทียบเท่ากัน แต่เป็นวิธีที่เร็วและง่ายที่สุดในการเข้าใกล้เอฟเฟกต์เดียวกันใน vanilla JavaScript


39
สำหรับ downvoters ของคำตอบนี้ (และอื่น ๆ ด้านล่าง): เมื่อถามคำถามนี้มันก็พูดง่ายๆว่า: "$ (document) .ready () ใน javascript คืออะไรไม่ใช่ jquery มันคืออะไร" ดูเหมือนว่าเขากำลังถามสิ่งที่มีความหมายในวานิลลาจาวาสคริปต์ธรรมดาโดยที่ไม่โหลด jQuery ในคำตอบของฉันฉันพยายามตอบคำถามนั้นรวมทั้งให้คำตอบที่ง่ายที่สุดสำหรับ JavaScript แบบธรรมดา - วานิลลาที่ไม่มี jQuery หรือไลบรารีอื่น ๆ ในกรณีที่เป็นสิ่งที่เขาหมายถึง โปรดทราบว่ามีการเพิ่มบริบทเพิ่มเติมทั้งหมดโดยผู้อื่นที่คาดเดาว่าคำถามนั้นถามอะไรไม่ใช่โปสเตอร์ดั้งเดิม
Brian Campbell

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

เนื้อความโหลดอาจเป็นทางเลือกเช่นกัน:

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

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

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

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