2014-11-16 11 views
8

Ho una pagina html con alcuni contenuti pre-renderizzati e alcuni contenuti ancora non renderizzati. Voglio visualizzare immediatamente il contenuto pre-renderizzato e quindi iniziare a mostrare il resto del contenuto. Non sto utilizzando jQuery.Esegui javascript al termine del caricamento della pagina

Vedere lo snippet seguente. Ho provato questo vari modi, tra cui iniettare il mio script prima del tag body di chiusura e fornire il mio script per popolare il DOM come callback a window.onload, document.body.onload e document.addEventListener('DOMContentLoaded'). In ogni caso, la pagina non visualizza i contenuti pre-renderizzati fino a quando non viene eseguito il rendering del resto del contenuto.

<html><head></head> 
 
    <body> 
 
    <header>What it is, my doge?</header> 
 
    <div id="main"></div> 
 
    <script> 
 
     var main = document.getElementById('main'); 
 
     for (var i = 0; i < 500; i++) 
 
     main.innerText += new Date(); 
 
    </script> 
 
    </body> 
 
</html>

<html><head></head> 
 
    <body> 
 
    <header>What it is, my doge?</header> 
 
    <div id="main"></div> 
 
    <script> 
 
     var main = document.getElementById('main'); 
 
     document.body.onload = function() { 
 
     for (var i = 0; i < 500; i++) 
 
      main.innerText += new Date(); 
 
     }; 
 
    </script> 
 
    </body> 
 
</html>

<html><head></head> 
 
     <body> 
 
     <header>What it is, my doge?</header> 
 
     <div id="main"></div> 
 
     <script> 
 
      var main = document.getElementById('main'); 
 
      window.onload = function() { 
 
      for (var i = 0; i < 500; i++) 
 
       main.innerText += new Date(); 
 
      }; 
 
     </script> 
 
     </body> 
 
    </html>

<html><head></head> 
 
     <body> 
 
     <header>What it is, my doge?</header> 
 
     <div id="main"></div> 
 
     <script> 
 
      var main = document.getElementById('main'); 
 
      document.addEventListener('DOMContentLoaded', function() { 
 
      for (var i = 0; i < 500; i++) 
 
       main.innerText += new Date(); 
 
      }); 
 
     </script> 
 
     </body> 
 
    </html>

Un caso che ha lavorato sia con window.setTimeout 0 timeout. Tuttavia, questo semplicemente rimanda la funzione fino a quando non rimane nulla da fare. È questa la migliore pratica, qui?

<html><head></head> 
 
<body> 
 
    <header>What it is, my doge?</header> 
 
    <div id="main"></div> 
 
    <script> 
 
     var main = document.getElementById('main'); 
 
     window.setTimeout(function() { 
 
     for (var i = 0; i < 500; i++) 
 
      main.innerText += new Date(); 
 
     }, 0); 
 
    </script> 
 
</body> 
 
</html>

+1

1) abbiamo bisogno di codice qui. 2) la tua descrizione non corrisponde al violino. 3) window.onload si attiverà dopo aver caricato tutto il contenuto. Tutto quello che devi fare è mettere la tua chiamata prima del tag '' – mplungjan

+0

il violino è esattamente un esempio di ciò che descrivi e chiaramente non funziona. –

+0

@MatthewJamesDavis Come viene reso il contenuto non reso? –

risposta

10

In termini di una migliore pratica, non ce n'è uno. In termini di buono, comune e accettabile pratiche, ce ne sono una manciata.Hai colpito una:

setTimeout(function() { }, 1); 

In questo caso, la funzione viene eseguita entro the browser's minimum timeout period dopo tutti gli altri in linea finisce di lavorazione.

Allo stesso modo, se si vuole garantire la funzione viene eseguito poco dopo certa condizione è vera, utilizzare un intervallo:

var readyCheck = setInterval(function() { 
    if (readyCondition) { 
    /* do stuff */ 
    clearInterval(readyCheck); 
    } 
}, 1); 

ho usato una soluzione simile, ma più generalizzata nel mio lavoro . Mi definisco una funzione di supporto nell'intestazione:

var upon = function(test, fn) { 
    if (typeof(test) == 'function' && test()) { 
     fn(); 
    } else if (typeof(test) == 'string' && window[test]) { 
     fn(); 
    } else { 
     setTimeout(function() { upon(test, fn); }, 50); 
    } 
}; // upon() 

... e innescare altri funzionalità quando le dipendenze sono risolte:

upon(function() { return MyNS.Thingy; }, function() { 
    // stuff that depends on MyNS.Thingy 
}); 

upon(function() { return document.readyState == 'complete';}, function() { 
    // stuff that depends on a fully rendered document 
}); 

Oppure, se si desidera una più autorevole buone prassi , segui l'esempio di Google. Crea un async script esterno e iniettare prima della prima intestazione script: soluzione

var s = document.createElement('script'); s.type = 'text/javascript'; s.async = true; 
s.src = '/path/to/script.js'; 
var header_scripts = document.getElementsByTagName('script')[0]; 
header_scripts.parentNode.insertBefore(s, header_scripts); 

di Google funziona teoricamente su tutti i browser per ottenere uno script esterno di esecuzione non appena possibile, senza interferire con il documento di carico (IE < 10?).

Se si desidera un autorevole comune pratica, controllare la fonte per la soluzione di jQuery onready.

+0

qualche idea perché Google suggerisce di suggerirti di iniettarlo invece di includerlo? –

+0

@MatthewJamesDavis [Due ragioni] (http://stackoverflow.com/questions/14815481/why-does-google-analytics-dynamically-inject-javascript-into-the-page) che io conosca.Solo uno sembra pertinente qui: alcuni browser non supportano l'attributo 'async'. – svidgen

+0

@MatthewJamesDavis Consultare il supporto del browser per 'async' qui: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script#Browser_compatibility – svidgen

0

Penso che ciò che si vuole fare è utilizzare un evento onload sul tag. In questo modo prima il "Che cos'è, il mio doge?" messaggio verrà visualizzato mentre il javascript viene elaborato.

Ho anche impostato un timeout all'interno del ciclo, in modo da poter vedere meglio le linee da aggiungere.

<html> 
    <head> 
     <script> 
      myFunction = function() { 
       for (var i = 1000; i > 0; i--) { 
        setTimeout(function() { 
         main.innerText += new Date(); 
        }, 100); 
       } 
      }; 
     </script> 
    </head> 

    <body onload="myFunction()"> 
     <header>What it is, my doge?</header> 
     <div id="main"></div> 
    </body> 
</html> 
+0

Apprezzo la risposta. Tuttavia, questo non è ottimale come l'idea che ho postato, impostando una chiamata a window.setTimeout al di fuori della callback con un timeout di 0, che è molto più veloce. –

4

A seconda delle esigenze del browser è possibile utilizzare il tag async e importare lo script dopo il caricamento di contenuti. Questo probabilmente ha lo stesso effetto di setTimeout(func, 0), ma forse è un po 'meno hacky.

Vedi http://plnkr.co/edit/7DlNWNHnyX5s6UE8AFiU?p=preview

html:

... 
<body> 
    <h1 id="main">Hello Plunker!</h1> 
    <script async src="script.js"></script> 
</body> 
... 

script.js:

for(var i=0; i<500; ++i) { 
    document.getElementById('main').innerText += new Date(); 
} 
+0

è molto meno hacky. il metodo setTimeout dice "hey, ferma tutto mentre scarichi questo script, poi finisci di fare qualunque cosa tu stia facendo, quindi esegui lo script" dove async dice "finisci di fare tutte le cose, poi esegui lo script ogni volta che è pronto" –

1

Ho usato questo per effettuare prima:

var everythingLoaded = setInterval(function() { 
    if (/loaded|complete/.test(document.readyState)) { 
    clearInterval(everythingLoaded); 
    init(); // this is the function that gets called when everything is loaded 
    } 
}, 10);