Tüm sayfa yüklenmeden javascript çalıştırabilir miyim?


Yanıtlar:


189

Sadece can seni, ancak bunun için özel bir çaba yapmak zorunda değil istediğiniz yapmazsan için. :-)

Tarayıcı script, HTML'yi ayrıştırırken klasik bir etiketle karşılaştığında , ayrıştırmayı durdurur ve komut dosyasını çalıştıran JavaScript yorumlayıcısına aktarır. Ayrıştırıcı, betik yürütmesi tamamlanana kadar devam etmez (çünkü betik document.write, ayrıştırıcının işlemesi gereken çıktı biçimlendirmesi için çağrılar yapabilir ).

Bu varsayılan davranıştır, ancak komut dosyasının yürütülmesini geciktirmek için birkaç seçeneğiniz vardır:

  1. JavaScript modüllerini kullanın. Bir type="module"komut dosyası, HTML tam olarak ayrıştırılana ve ilk DOM yaratılana kadar ertelenir . Modülleri kullanmanın birincil nedeni bu değil, ancak nedenlerinden biri:

    <script type="module" src="./my-code.js"></script>
    <!-- Or -->
    <script type="module">
    // Your code here
    </script>
    

    Kod getirilecek (ayrı ise) ve HTML ayrıştırmasıyla paralel olarak ayrıştırılacak, ancak HTML ayrıştırması tamamlanana kadar çalıştırılmayacaktır . (Modül kodunuz kendi dosyası yerine satır içi ise, HTML ayrıştırması tamamlanana kadar da ertelenir.)

    Bu cevabı 2010'da ilk yazdığımda bu mevcut değildi, ancak 2020'de, tüm büyük modern tarayıcılar modülleri yerel olarak destekliyor ve eski tarayıcıları desteklemeniz gerekiyorsa, Webpack ve Rollup.js gibi paketleyicileri kullanabilirsiniz.

  2. Kullan deferklasik bir komut dosyası etiketi üzerinde niteliğini:

    <script defer src="./my-code.js"></script>
    

    Modülde olduğu gibi, içindeki kod my-code.jsHTML ayrıştırmasına paralel olarak getirilecek ve ayrıştırılacaktır, ancak HTML ayrıştırması tamamlanana kadar çalıştırılmayacaktır . Ancak , defersatır içi komut dosyası içeriğiyle çalışmaz, yalnızca üzerinden referans verilen harici dosyalarla çalışmaz src.

  3. Ben ne olduğunu sanmıyorum sen istiyorsun ama kullanabilirsiniz asyncHTML ayrıştırma tam olmasa bile, HTML ayrıştırma paralel olarak JavaScript kodunu almak için tarayıcı anlatmak için öznitelik, ama sonra en kısa sürede çalıştırmak . Bunu bir type="module"etikete koyabilir veya deferklasik bir scriptetiket yerine kullanabilirsiniz .

  4. Put scripthemen önce kapanış için, belgenin sonundaki etiketi </body>etiketi:

    <!doctype html>
    <html>
    <!-- ... -->
    <body>
    <!-- The document's HTML goes here -->
    <script type="module" src="./my-code.js"></script><!-- Or inline script -->
    </body>
    </html>
    

    Bu şekilde, kod karşılaştığı anda çalıştırılsa bile, üstündeki HTML tarafından tanımlanan tüm öğeler mevcuttur ve kullanıma hazırdır.

    Eskiden bu, bazı tarayıcılarda ek bir gecikmeye neden oluyordu çünkü scriptetiketle karşılaşılıncaya kadar kodu getirmeye başlamıyorlardı , ancak modern tarayıcılar ileriyi tarıyor ve önceden getirmeye başlıyordu. Yine de bu noktada bu çok fazla üçüncü seçenek, hem modül hem deferde daha iyi seçenekler.

Spec yararlı bir diyagramı olan bir ham gösteren scriptetiket, defer, async, type="module", ve type="module" asyncJavaScript kodu getirilen ve çalıştırıldığında zamanlama ve:

görüntü açıklamasını buraya girin

Aşağıda, varsayılan davranışın bir örneği olan ham bir scriptetiket verilmiştir:

.found {
    color: green;
}
<p>Paragraph 1</p>
<script>
    if (typeof NodeList !== "undefined" && !NodeList.prototype.forEach) {
        NodeList.prototype.forEach = Array.prototype.forEach;
    }
    document.querySelectorAll("p").forEach(p => {
        p.classList.add("found");
    });
</script>
<p>Paragraph 2</p>

( Bu kodla ilgili ayrıntılar için cevabıma buradan bakın NodeList.)

Bunu çalıştırdığınızda, "Paragraf 1" i yeşil olarak görürsünüz, ancak "Paragraf 2" siyahtır, çünkü komut dosyası HTML ayrıştırmasıyla eşzamanlı olarak çalışır ve bu nedenle, ikinciyi değil yalnızca ilk paragrafı bulur.

Buna karşılık, işte bir type="module"komut dosyası:

.found {
    color: green;
}
<p>Paragraph 1</p>
<script type="module">
    document.querySelectorAll("p").forEach(p => {
        p.classList.add("found");
    });
</script>
<p>Paragraph 2</p>

Şimdi ikisinin de nasıl yeşil olduğuna dikkat edin; kod, HTML ayrıştırması tamamlanana kadar çalışmadı. Bu aynı zamanda defer scriptharici içeriğe sahip (ancak satır içi içerik değil) için de geçerli olacaktır.

(Orada NodeListkontrole gerek yoktu çünkü modern tarayıcı destekleyen modüller zaten forEachaçık NodeList.)

Bu modern dünyada, DOMContentLoadedPrototypeJS, jQuery, ExtJS, Dojo ve diğerlerinin gün içinde sağladığı (ve hala sağladıkları) "hazır" özelliğinin gerçek bir değeri yoktur ; sadece modülleri kullanın veya defer. Hatta eski günlerde, bunları kullanmak için pek bir neden yoktu (ve genellikle sayfa çünkü tüm jQuery kütüphanesi yüklü iken sunum tutan, yanlış kullanıldı scriptoldu headbelgenin sonra yerine), bir şey bazı geliştiriciler de Google erken işaretledi. Bu aynı zamanda YUI tavsiyesinin komut dosyalarını günün sonunda bodytekrar koyma nedeninin bir parçasıydı .


Veya hepsini bir işleve koyun ve yerleştirin <body onload="doIt()>".
Justin Liu

@JustinLiu - loadOlay , sayfa yükleme döngüsünün çok geç döneminde gerçekleşir, o zamana kadar JavaScript'inizi çalıştırmak için beklemek neredeyse hiçbir zaman en iyi uygulama değildir. Ama evet, bu bir seçenektir. 2020 için cevabı elden geçirdim, btw.
TJ Crowder

Ya da kullanabilirsinizdocument.addEventListener('DOMContentLoaded', function(){ //doyour stuff })
Justin Liu

@JustinLiu - Evet, son paragrafa bakın. :-) Hiç ihtiyaç görmedim, ama sen yapabilirsin.
TJ Crowder

@JustinLiu - Bu zirveyi aşmaya başlıyor. Bir cevap göndermek istiyorsanız, lütfen bir cevap gönderin.
TJ Crowder

6

Javascript kodunu istediğiniz zaman çalıştırabilirsiniz. AFAIK, tarayıcının içinde bulunduğu <script> etiketine ulaştığı anda yürütülür. Ancak henüz yüklenmemiş öğelere erişemezsiniz.

Öyleyse, öğelere erişmeniz gerekiyorsa, DOM yüklenene kadar beklemelisiniz (bu, resimler ve diğer öğeler dahil olmak üzere tüm sayfanın yükleneceği anlamına gelmez. Bu, yalnızca belgenin çok daha önce yüklenen yapısıdır, bu nedenle genellikle kazanırsınız jQuery'deki DOMContentLoadedgibi olayı veya işlevleri kullanarak bir gecikme fark $.readyetmez).


2
DOMContentLoaded olayı, DOM hiyerarşisi tam olarak oluşturulur oluşturulmaz tetiklenir, load olayı, tüm resimler ve alt çerçevelerin yüklenmesi tamamlandığında bunu gerçekleştirir.
BeauCielBleu
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.