Pertanyaan Murni JavaScript setara dengan jQuery's $ .ready () - cara memanggil fungsi ketika halaman / DOM siap untuk itu [duplikat]


Pertanyaan ini sudah memiliki jawaban di sini:

Oke, ini mungkin hanya pertanyaan konyol, meskipun saya yakin ada banyak orang lain yang menanyakan pertanyaan yang sama dari waktu ke waktu. Saya, saya hanya ingin membuat 100% yakin tentang hal itu dengan cara baik. Dengan jQuery kita semua tahu yang indah

$('document').ready(function(){});

Namun, katakanlah saya ingin menjalankan fungsi yang ditulis dalam JavaScript standar tanpa pustaka yang mendukungnya, dan bahwa saya ingin meluncurkan fungsi segera setelah laman siap untuk menanganinya. Apa cara yang tepat untuk mendekati ini?

Saya tahu saya bisa melakukan:

window.onload="myFunction()";

... atau saya bisa menggunakan body menandai:

<body onload="myFunction()">

... atau saya bahkan bisa mencoba di bagian bawah halaman setelah semuanya, tetapi akhirnya body atau html tag seperti:

<script type="text/javascript">
   myFunction();
</script>

Apa itu lintas-browser (lama / baru) -compliant metode mengeluarkan satu atau lebih fungsi dengan cara seperti jQuery $.ready()?


907
2018-03-27 23:57


asal


Jawaban:


Hal yang paling sederhana untuk dilakukan tanpa adanya kerangka kerja yang melakukan semua kompatibilitas lintas-browser untuk Anda adalah dengan hanya menempatkan panggilan ke kode Anda di ujung tubuh. Ini lebih cepat untuk dijalankan daripada onload pawang karena ini hanya menunggu DOM siap, bukan untuk semua gambar dimuat. Dan, ini berfungsi di setiap browser.

<html>
<head>
</head>
<body>
Your HTML here

<script>
// self executing function here
(function() {
   // your page initialization code here
   // the DOM will be available here

})();
</script>
</body>
</html>

Jika Anda benar-benar tidak ingin melakukannya dengan cara ini dan Anda perlu kompatibilitas antar browser dan Anda tidak ingin menunggu window.onload, maka Anda mungkin harus melihat bagaimana kerangka kerja seperti jQuery mengimplementasikannya $(document).ready() metode. Ini cukup terlibat tergantung pada kemampuan browser.

Untuk memberi Anda sedikit gambaran apa yang dilakukan jQuery (yang akan berfungsi di mana pun tag skrip ditempatkan).

Jika didukung, akan mencoba standar:

document.addEventListener('DOMContentLoaded', fn, false);

dengan fallback ke:

window.addEventListener('load', fn, false )

atau untuk versi IE yang lebih lama, ia menggunakan:

document.attachEvent("onreadystatechange", fn);

dengan fallback ke:

window.attachEvent("onload", fn);

Dan, ada beberapa work-arounds di jalur kode IE yang saya tidak cukup ikuti, tetapi sepertinya itu ada hubungannya dengan frame.


Di sini adalah pengganti penuh untuk jQuery .ready() ditulis dalam javascript biasa:

(function(funcName, baseObj) {
    // The public function name defaults to window.docReady
    // but you can pass in your own object and own function name and those will be used
    // if you want to put them in a different namespace
    funcName = funcName || "docReady";
    baseObj = baseObj || window;
    var readyList = [];
    var readyFired = false;
    var readyEventHandlersInstalled = false;

    // call this when the document is ready
    // this function protects itself against being called more than once
    function ready() {
        if (!readyFired) {
            // this must be set to true before we start calling callbacks
            readyFired = true;
            for (var i = 0; i < readyList.length; i++) {
                // if a callback here happens to add new ready handlers,
                // the docReady() function will see that it already fired
                // and will schedule the callback to run right after
                // this event loop finishes so all handlers will still execute
                // in order and no new ones will be added to the readyList
                // while we are processing the list
                readyList[i].fn.call(window, readyList[i].ctx);
            }
            // allow any closures held by these functions to free
            readyList = [];
        }
    }

    function readyStateChange() {
        if ( document.readyState === "complete" ) {
            ready();
        }
    }

    // This is the one public interface
    // docReady(fn, context);
    // the context argument is optional - if present, it will be passed
    // as an argument to the callback
    baseObj[funcName] = function(callback, context) {
        if (typeof callback !== "function") {
            throw new TypeError("callback for docReady(fn) must be a function");
        }
        // if ready has already fired, then just schedule the callback
        // to fire asynchronously, but right away
        if (readyFired) {
            setTimeout(function() {callback(context);}, 1);
            return;
        } else {
            // add the function and context to the list
            readyList.push({fn: callback, ctx: context});
        }
        // if document already ready to go, schedule the ready function to run
        if (document.readyState === "complete") {
            setTimeout(ready, 1);
        } else if (!readyEventHandlersInstalled) {
            // otherwise if we don't have event handlers installed, install them
            if (document.addEventListener) {
                // first choice is DOMContentLoaded event
                document.addEventListener("DOMContentLoaded", ready, false);
                // backup is window load event
                window.addEventListener("load", ready, false);
            } else {
                // must be IE
                document.attachEvent("onreadystatechange", readyStateChange);
                window.attachEvent("onload", ready);
            }
            readyEventHandlersInstalled = true;
        }
    }
})("docReady", window);

Versi terbaru dari kode ini dibagikan secara publik di GitHub di https://github.com/jfriend00/docReady

Pemakaian:

// pass a function reference
docReady(fn);

// use an anonymous function
docReady(function() {
    // code here
});

// pass a function reference and a context
// the context will be passed to the function as the first argument
docReady(fn, context);

// use an anonymous function with a context
docReady(function(context) {
    // code here that can use the context argument that was passed to docReady
}, ctx);

Ini telah diuji dalam:

IE6 and up
Firefox 3.6 and up
Chrome 14 and up
Safari 5.1 and up
Opera 11.6 and up
Multiple iOS devices
Multiple Android devices

Pelaksanaan kerja dan test bed: http://jsfiddle.net/jfriend00/YfD3C/


Berikut ringkasan cara kerjanya:

  1. Buat sebuah IIFE (ekspresi fungsi segera dipanggil) sehingga kita dapat memiliki variabel keadaan non-publik.
  2. Deklarasikan fungsi publik docReady(fn, context)
  3. Kapan docReady(fn, context) dipanggil, periksa apakah handler siap telah dipecat. Jika demikian, cukup jadwalkan panggilan balik yang baru ditambahkan untuk diaktifkan setelah untaian JS ini selesai setTimeout(fn, 1).
  4. Jika handler yang siap belum diaktifkan, tambahkan panggilan balik baru ini ke daftar panggilan balik untuk dipanggil nanti.
  5. Periksa apakah dokumen sudah siap. Jika ya, laksanakan semua penangan yang siap.
  6. Jika kami belum menginstal pendengar acara untuk mengetahui kapan dokumen menjadi siap, maka instal sekarang.
  7. Jika document.addEventListener ada, kemudian instal penangan kejadian menggunakan .addEventListener() untuk berdua "DOMContentLoaded" dan "load" acara. "Beban" adalah acara cadangan untuk keamanan dan seharusnya tidak diperlukan.
  8. Jika document.addEventListener tidak ada, kemudian instal penangan kejadian menggunakan .attachEvent() untuk "onreadystatechange" dan "onload" acara.
  9. Dalam onreadystatechange acara, periksa untuk melihat apakah document.readyState === "complete" dan jika demikian, panggil fungsi untuk memecat semua penangan yang siap.
  10. Dalam semua penangan kejadian lainnya, panggil fungsi untuk memecat semua penangan yang siap.
  11. Dalam fungsi untuk memanggil semua handler yang siap, periksa variabel keadaan untuk melihat apakah kita sudah dipecat. Jika kita punya, jangan lakukan apapun. Jika kita belum dipanggil, maka lewati susunan fungsi siap dan panggil masing-masing dalam urutan yang telah ditambahkan. Tetapkan bendera untuk menunjukkan ini semua telah dipanggil sehingga mereka tidak pernah dieksekusi lebih dari satu kali.
  12. Hapus array fungsi sehingga setiap penutupan yang mungkin mereka gunakan dapat dibebaskan.

Penangan yang terdaftar dengan docReady() dijamin akan dipecat sesuai urutan terdaftar.

Jika Anda menelepon docReady(fn) setelah dokumen sudah siap, callback akan dijadwalkan untuk dijalankan segera setelah rangkaian eksekusi saat ini selesai digunakan setTimeout(fn, 1). Hal ini memungkinkan kode panggilan untuk selalu menganggap bahwa mereka adalah callback async yang akan dipanggil nanti, bahkan jika kemudian segera setelah thread JS saat ini selesai dan mempertahankan urutan panggilan.


1350
2018-03-28 00:46



Saya ingin menyebutkan beberapa cara yang mungkin di sini bersama dengan trik javascript murni yang berfungsi di semua browser:

// with jQuery 
$(document).ready(function(){ /* ... */ });

// shorter jQuery version 
$(function(){ /* ... */ });

// without jQuery (doesn't work in older IEs)
document.addEventListener('DOMContentLoaded', function(){ 
    // your code goes here
}, false);

// and here's the trick (works everywhere)
function r(f){/in/.test(document.readyState)?setTimeout('r('+f+')',9):f()}
// use like
r(function(){
    alert('DOM Ready!');
});

Triknya di sini, seperti yang dijelaskan oleh penulis asli, apakah kita sedang memeriksa document.readyState milik. Jika itu berisi string in (seperti dalam uninitialized dan loading, dua pertama Negara siap DOM dari 5) kami menetapkan batas waktu dan memeriksa lagi. Jika tidak, kita menjalankan fungsi yang dilewati.

Dan inilah yang jsFiddle untuk trik yang mana berfungsi di semua browser. 

Terimakasih untuk Tutorialzine untuk memasukkan ini ke dalam buku mereka.


99
2018-05-19 07:58



Jika Anda melakukannya VANILA polos JavaScript tanpa jQuery, maka Anda harus menggunakan (Internet Explorer 9 atau lebih baru):

document.addEventListener("DOMContentLoaded", function(event) {
    // Your code to run since DOM is loaded and ready
});

Di atas adalah setara dengan jQuery .ready:

$(document).ready(function() {
    console.log("Ready!");
});

Yang JUGA bisa ditulis SHORTHAND seperti ini, yang jQuery akan berjalan setelah siap genap terjadi.

$(function() {
    console.log("ready!");
});

BUKAN BINGUNG DENGAN DI BAWAH (yang tidak dimaksudkan untuk menjadi DOM siap):

JANGAN menggunakan IIFE seperti ini yang mengeksekusi diri:

 Example:

(function() {
   // Your page initialization code here  - WRONG
   // The DOM will be available here   - WRONG
})();

IIFE ini TIDAK akan menunggu DOM Anda dimuat. (Saya bahkan berbicara tentang browser Chrome versi terbaru!)


81
2017-07-01 20:31



Diuji di IE9, dan Firefox dan Chrome terbaru dan juga didukung di IE8.

document.onreadystatechange = function () {
  var state = document.readyState;
  if (state == 'interactive') {
      init();
  } else if (state == 'complete') {
      initOnCompleteLoad();
  }
}​;

Contoh: http://jsfiddle.net/electricvisions/Jacck/

UPDATE - versi reusable

Saya baru saja mengembangkan yang berikut ini. Ini adalah persamaan yang agak sederhana untuk jQuery atau Dom yang siap tanpa kompatibilitas ke belakang. Mungkin perlu penyempurnaan lebih lanjut. Diuji dalam versi terbaru Chrome, Firefox, dan IE (10/11) dan seharusnya berfungsi di browser lama seperti yang dikomentari. Saya akan memperbarui jika saya menemukan masalah apa pun.

window.readyHandlers = [];
window.ready = function ready(handler) {
  window.readyHandlers.push(handler);
  handleState();
};

window.handleState = function handleState () {
  if (['interactive', 'complete'].indexOf(document.readyState) > -1) {
    while(window.readyHandlers.length > 0) {
      (window.readyHandlers.shift())();
    }
  }
};

document.onreadystatechange = window.handleState;

Pemakaian:

ready(function () {
  // your code here
});

Ini ditulis untuk menangani pemuatan async JS tetapi Anda mungkin ingin menyinkronkan memuat skrip ini terlebih dahulu kecuali Anda sedang meminimalkan. Saya telah menemukan itu berguna dalam pengembangan.

Peramban modern juga mendukung pemuatan skrip asinkron yang semakin meningkatkan pengalaman. Dukungan untuk async berarti banyak skrip dapat diunduh secara bersamaan semua saat masih menampilkan halaman. Waspadalah saat tergantung pada skrip lain yang dimuat secara asinkron atau gunakan penambang atau sesuatu seperti browserify untuk menangani dependensi.


71
2018-06-10 13:27



Orang-orang baik di HubSpot memiliki sumber di mana Anda dapat menemukan metodologi Javascript murni untuk mencapai banyak kebaikan jQuery - termasuk ready

http://youmightnotneedjquery.com/#ready

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

contoh penggunaan inline:

ready(function() { alert('hello'); });

17
2018-03-28 00:46



Metode Anda (menempatkan skrip sebelum tag badan penutup)

<script>
   myFunction()
</script>
</body>
</html>

adalah cara yang andal untuk mendukung peramban lama dan baru.


7
2017-11-24 05:15



Siap

function ready(fn){var d=document;(d.readyState=='loading')?d.addEventListener('DOMContentLoaded',fn):fn();}

Gunakan suka

ready(function(){
    //some code
});

Untuk kode diri memohon

(function(fn){var d=document;(d.readyState=='loading')?d.addEventListener('DOMContentLoaded',fn):fn();})(function(){

    //Some Code here
    //DOM is avaliable
    //var h1s = document.querySelector("h1");

});

Dukungan: IE9 +


4
2018-06-19 06:03



Saya tidak yakin apa yang Anda tanyakan, tetapi mungkin ini dapat membantu:

window.onload = function(){
    // Code. . .

}

Atau:

window.onload = main;

function main(){
    // Code. . .

}

3
2018-03-28 00:04



document.ondomcontentready=function(){} harus melakukan trik, tetapi tidak memiliki kompatibilitas browser lengkap.

Sepertinya Anda hanya perlu menggunakan min jQuery


2
2017-10-28 17:52



Ini adalah versi bersih-bersih, non-eval-using dari Ram-swaroop variasi "berfungsi di semua browser" - berfungsi di semua browser!

function onReady(yourMethod) {
  var readyStateCheckInterval = setInterval(function() {
    if (document && document.readyState === 'complete') { // Or 'interactive'
      clearInterval(readyStateCheckInterval);
      yourMethod();
    }
  }, 10);
}
// use like
onReady(function() { alert('hello'); } );

Itu memang menunggu tambahan 10 ms untuk dijalankan, namun, inilah cara yang lebih rumit yang seharusnya tidak:

function onReady(yourMethod) {
  if (document.readyState === 'complete') { // Or also compare to 'interactive'
    setTimeout(yourMethod, 1); // Schedule to run immediately
  }
  else {
    readyStateCheckInterval = setInterval(function() {
      if (document.readyState === 'complete') { // Or also compare to 'interactive'
        clearInterval(readyStateCheckInterval);
        yourMethod();
      }
    }, 10);
  }
}

// Use like
onReady(function() { alert('hello'); } );

// Or
onReady(functionName);

Lihat juga Bagaimana cara memeriksa apakah DOM sudah siap tanpa framework?.


2