Apa yang setara dengan non-jQuery dari '$ (dokumen) .ready ()'?

444

Apa yang setara dengan non-jQuery $(document).ready()?

TIMEX
sumber
4
Jika Anda ingin mereproduksi acara jQuery $(document).ready()tanpa menggunakan pustaka apa pun, coba lihat ini: stackoverflow.com/questions/1795089/…
CMS
@OP: lihat halaman 89 dari Teknik Pro JavaScript untuk implementasi JavaScript vanilla dari $(document).ready()- books.google.com/… . Ini juga menggunakan addEventabstraksi acara mengikat yang ditulis oleh Dean Edwards, kode yang juga ada dalam buku :)
Russ Cam
2
kemungkinan rangkap $ (dokumen). sudah setara tanpa jQuery
Qantas 94 Heavy

Jawaban:

74

Yang menyenangkan tentang itu $(document).ready()adalah api sebelumnya window.onload. Fungsi memuat menunggu hingga semuanya dimuat, termasuk aset eksternal dan gambar. $(document).readyNamun, kebakaran ketika pohon DOM selesai dan dapat dimanipulasi. Jika Anda ingin mencapai DOM siap, tanpa jQuery, Anda dapat memeriksa ke perpustakaan ini. Seseorang mengekstraksi readybagian dari jQuery. Ini bagus dan kecil dan Anda mungkin menemukan itu berguna:

sudah ada di Google Code

Doug Neiner
sumber
4
Jaringan kode DomReady! via @CMS di github: github.com/cms/domready/network
Kzqai
44
Ini tidak menjawab pertanyaan dan juga tidak menunjukkan kode non-jQuery. Bagaimana cara mendapatkan begitu banyak upvotes?
Daniel W.
3
@DanielW. Karena itu sederhana dan praktis. Sebagian besar dari kita datang ke sini mencari cara untuk memastikan DOM siap digunakan oleh kode javascript.
abarazal
Ya tetapi beberapa dari kita datang ke sini untuk jawaban yang sebenarnya.
Slbox
613

Ini berfungsi dengan baik, dari ECMA

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

Tidak window.onloadsama dengan JQuery $(document).readykarena $(document).readyhanya menunggu ke pohon DOM sambil window.onloadmemeriksa semua elemen termasuk aset dan gambar eksternal.

EDIT : Menambahkan IE8 dan yang lebih lama setara, berkat pengamatan Jan Derk . Anda dapat membaca sumber kode ini di MDN di tautan ini :

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

Ada opsi lain selain "interactive". Lihat tautan MDN untuk detailnya.

sospedra
sumber
Setuju dengan Benjamin. Anda tidak bisa begitu saja menggunakan attachEvent. Misalnya di Chrome Anda mendapatkan: Uncaught TypeError: document.attachEvent bukan fungsi. Gunakan jawaban yang ditautkan oleh Jan Derk.
Manuel Arwed Schmidt
9
Bagaimana jika dokumen sudah dimuat saat skrip ini dipanggil? Tidak ada yang akan terjadi sama sekali :(
oriadam
8
@Deerloper Tidak, hanya mencobanya di konsol Chrome - tidak ada yang terjadi: document.addEventListener("DOMContentLoaded",function(){console.log(123)})coba sekarang
oriadam
2
Dukungan DOMContentLoaded di browser: caniuse.com/domcontentloaded
Guillaume Husta
1
@elliottregan itu benar saya menghapus komentar untuk menghindari mencemari utas ini saya sarankan Anda semua melakukan hal yang sama :) Dan biarkan satu komentar jika perlu menunjukkan komentar jika diperlukan. Karena itu tambahan karena melampaui pertanyaan OC
sospedra
43

Suatu hal kecil yang saya kumpulkan

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

Bagaimana cara menggunakannya

<script src="domready.js"></script>
<script>
  domReady(function(event) {
    alert("dom is ready!");
  });
</script>

Anda juga dapat mengubah konteks di mana panggilan balik berjalan dengan memberikan argumen kedua

function init(event) {
  alert("check the console");
  this.log(event);
}

domReady(init, console);
Terima kasih
sumber
2
Terima kasih. Saya suka fakta bahwa itu kompatibel ke belakang. Bergerak maju tidak berarti meninggalkan orang yang kurang beruntung. Tidak dapat menggunakan browser modern (untuk alasan apa pun) sangat disayangkan ...
CO
28

Sekarang tahun 2018 inilah metode cepat dan sederhana.

Ini akan menambah pendengar acara, tetapi jika sudah dipecat kami akan memeriksa bahwa dom dalam keadaan siap atau sudah selesai. Ini dapat diaktifkan sebelum atau setelah sub-sumber daya selesai memuat (gambar, stylesheet, bingkai, dll).

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!"));

Bacaan tambahan


Memperbarui

Berikut beberapa pembantu utilitas cepat menggunakan ES6 Impor & Ekspor standar yang saya tulis yang menyertakan TypeScript juga. Mungkin saya bisa menyiasati untuk membuat ini perpustakaan cepat yang dapat diinstal ke proyek sebagai ketergantungan.

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

Janji

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);
  }
});
CTS_AE
sumber
16

Menurut http://youmightnotneedjquery.com/#ready pengganti yang bagus yang masih berfungsi dengan IE8 adalah

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

perbaikan : Secara pribadi saya juga akan memeriksa apakah jenis fnfungsi. Dan sebagai @elliottregan disarankan hapus pendengar acara setelah digunakan.

Alasan saya menjawab pertanyaan ini terlambat adalah karena saya mencari jawaban ini tetapi tidak dapat menemukannya di sini. Dan saya pikir ini adalah solusi terbaik.

Thomas secara online
sumber
1
Ya, ini jawaban terbaik menurut saya. Mudah dibaca, dan mengeksekusi kode bahkan jika DOM sudah dimuat. Satu-satunya hal yang saya tambahkan adalah menghapus eventlistener setelah acara dipecat.
elliottregan
14

Ada pengganti berbasis standar, DOMContentLoaded yang didukung oleh lebih dari 90% browser, tetapi bukan IE8 (Jadi, di bawah ini, gunakan kode oleh JQuery untuk dukungan browser) :

document.addEventListener("DOMContentLoaded", function(event) { 
  //do work
});

Fungsi asli jQuery jauh lebih rumit dari sekedar window.onload, seperti yang digambarkan di bawah ini.

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 );
}
Zigri2612
sumber
1
JQuery baru menjatuhkan dukungan untuk browser lama dan sekarang mereka hanya memiliki DOMContentLoadeddan loadmenggunakan acara addEventListener, dan pertama yang api menghapus kedua pendengar, sehingga tidak memecat dua kali.
jcubic
8

Dalam JavaScript vanilla biasa, tanpa perpustakaan? Itu kesalahan.$hanyalah sebuah pengidentifikasi, dan tidak terdefinisi kecuali Anda mendefinisikannya.

jQuery mendefinisikan $sebagai "objek segalanya" miliknya sendiri (juga dikenal sebagai jQueryAnda dapat menggunakannya tanpa bertentangan dengan pustaka lain). Jika Anda tidak menggunakan jQuery (atau perpustakaan lain yang mendefinisikannya), maka $tidak akan ditentukan.

Atau apakah Anda bertanya apa yang setara dalam JavaScript biasa? Dalam hal ini, Anda mungkin ingin window.onload, yang tidak persis setara, tetapi merupakan cara tercepat dan termudah untuk mendekati efek yang sama dalam JavaScript vanilla.

Brian Campbell
sumber
39
Untuk banyak downvoters dari jawaban ini (dan yang lainnya di bawah): ketika pertanyaan ini diajukan, ia hanya mengatakan: "Apa itu $ (dokumen). Sudah () dalam javascript? Bukan jquery. Apa itu?" Kedengarannya dia bertanya apa artinya di JavaScript vanilla polos tanpa jQuery dimuat. Dalam jawaban saya, saya mencoba untuk menjawab pertanyaan itu, serta memberikan jawaban mudah terdekat untuk JavaScript polos-vanilla tanpa jQuery atau perpustakaan lain jika itu yang dia maksud. Perhatikan bahwa semua konteks tambahan ditambahkan oleh orang lain yang menebak-nebak pertanyaan yang diajukan, bukan poster aslinya.
Brian Campbell
5

Cara termudah di browser terbaru adalah menggunakan GlobalEventHandlers yang sesuai , diDOMContentLoaded , onload , onloadeddata (...)

onDOMContentLoaded = (function(){ console.log("DOM ready!") })()

onload = (function(){ console.log("Page fully loaded!") })()

onloadeddata = (function(){ console.log("Data loaded!") })()

Acara DOMContentLoaded dipecat ketika dokumen HTML awal telah dimuat dan diurai sepenuhnya, tanpa menunggu stylesheet, gambar, dan subframe selesai dimuat. Event load yang sangat berbeda harus digunakan hanya untuk mendeteksi halaman yang dimuat penuh. Ini adalah kesalahan yang sangat populer untuk menggunakan load di mana DOMContentLoaded akan jauh lebih tepat, jadi berhati-hatilah.

https://developer.mozilla.org/en-US/docs/Web/Events/DOMContentLoaded

Fungsi yang digunakan adalah IIFE, sangat berguna dalam kasus ini, karena memicu dirinya sendiri ketika siap:

https://en.wikipedia.org/wiki/Immediately-invoked_function_expression

Jelas lebih tepat untuk menempatkannya di akhir skrip apa pun.

Di ES6, kita juga bisa menuliskannya sebagai fungsi panah:

onload = (() => { console.log("ES6 page fully loaded!") })()

Yang terbaik adalah menggunakan elemen DOM, kita bisa menunggu variabel siap, yang memicu IIFE panah.

Perilaku tersebut akan sama, tetapi dengan dampak memori yang lebih sedikit.

footer = (() => { console.log("Footer loaded!") })()
<div id="footer">

Dalam banyak kasus, objek dokumen juga memicu ketika siap , setidaknya di browser saya. Sintaksnya sangat bagus, tetapi perlu pengujian lebih lanjut tentang kompatibilitas.

document=(()=>{    /*Ready*/   })()
NVRM
sumber
Bisakah pemicu IIFE sebelum DOM selesai memuat elemen setelahnya?
CTS_AE
Tentu, itu hanya sebuah fungsi, fungsi anonim, dalam penutupan.
NVRM
0

Tubuh onLoad juga bisa menjadi alternatif:

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

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

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

</body>
</html>
joan16v
sumber