Je veux exécuter un peu de javascript avant que toute la page ne soit chargée. Est-ce possible? Ou le code commence-t-il à s'exécuter </html>
?
javascript
html
pique-nique
la source
la source
Réponses:
Non seulement vous le pouvez , mais vous devez faire un effort particulier pour ne pas le faire si vous ne le souhaitez pas. :-)
Lorsque le navigateur rencontre une
script
balise classique lors de l'analyse du HTML, il arrête l'analyse et passe la main à l'interpréteur JavaScript, qui exécute le script. L'analyseur ne continue pas tant que l'exécution du script n'est pas terminée (car le script peut effectuer desdocument.write
appels au balisage de sortie que l'analyseur doit gérer).C'est le comportement par défaut, mais vous avez quelques options pour retarder l'exécution du script:
Utilisez des modules JavaScript. Un
type="module"
script est différé jusqu'à ce que le HTML ait été entièrement analysé et le DOM initial créé. Ce n'est pas la principale raison d'utiliser des modules, mais c'est l'une des raisons:Le code sera récupéré (s'il est séparé) et analysé en parallèle avec l'analyse HTML, mais ne sera pas exécuté tant que l'analyse HTML n'est pas terminée. (Si le code de votre module est en ligne plutôt que dans son propre fichier, il est également différé jusqu'à ce que l'analyse HTML soit terminée.)
Cela n'était pas disponible lorsque j'ai écrit cette réponse pour la première fois en 2010, mais ici en 2020, tous les principaux navigateurs modernes prennent en charge les modules de manière native, et si vous avez besoin de prendre en charge des navigateurs plus anciens, vous pouvez utiliser des bundles comme Webpack et Rollup.js.
Utilisez l'
defer
attribut sur une balise de script classique:Comme pour le module, le code dans
my-code.js
sera récupéré et analysé en parallèle avec l'analyse HTML, mais ne sera pas exécuté tant que l'analyse HTML n'est pas terminée. Mais ,defer
ne fonctionne pas avec le contenu de script en ligne, uniquement avec des fichiers externes référencés viasrc
.Je ne pense pas que ce soit ce que vous voulez, mais vous pouvez utiliser l'
async
attribut pour indiquer au navigateur de récupérer le code JavaScript en parallèle avec l'analyse HTML, mais l'exécuter dès que possible, même si l'analyse HTML n'est pas terminée . Vous pouvez le mettre sur untype="module"
tag ou l'utiliser à la place d'defer
unscript
tag classique .Placez la
script
balise à la fin du document, juste avant la</body>
balise de fermeture :De cette façon, même si le code est exécuté dès sa rencontre, tous les éléments définis par le HTML ci-dessus existent et sont prêts à être utilisés.
Auparavant, cela provoquait un retard supplémentaire sur certains navigateurs car ils ne commenceraient pas à récupérer le code tant que la
script
balise n'était pas rencontrée, mais les navigateurs modernes analysent à l'avance et commencent la prélecture. Pourtant, c'est vraiment le troisième choix à ce stade, les deux modules etdefer
sont de meilleures options.La spécification a un diagramme utile montrant une première
script
étiquette,defer
,async
,type="module"
ettype="module" async
et le moment où le code JavaScript est extrait et exécutez:Voici un exemple du comportement par défaut, une
script
balise brute :(Voir ma réponse ici pour plus de détails sur ce
NodeList
code.)Lorsque vous exécutez cela, vous voyez «Paragraphe 1» en vert, mais «Paragraphe 2» est noir, car le script s'est exécuté de manière synchrone avec l'analyse HTML et n'a donc trouvé que le premier paragraphe, pas le second.
En revanche, voici un
type="module"
script:Remarquez comment ils sont tous les deux verts maintenant; le code n'a pas été exécuté tant que l'analyse HTML n'était pas terminée. Ce serait également vrai avec un
defer
script
contenu externe (mais pas un contenu en ligne).(Il n'y avait pas besoin pour le
NodeList
contrôle là parce que tous les modules supportant navigateur moderne a déjàforEach
surNodeList
.)Dans ce monde moderne, il n'y a aucune valeur réelle à l'
DOMContentLoaded
événement de la fonctionnalité «prête» que PrototypeJS, jQuery, ExtJS, Dojo et la plupart des autres ont fourni à l'époque (et fournissent toujours); utilisez simplement des modules oudefer
. Même à l'époque, il n'y avait pas beaucoup de raisons de les utiliser (et ils étaient souvent utilisés de manière incorrecte, bloquant la présentation de la page alors que toute la bibliothèque jQuery était chargée parce que lescript
était dans le documenthead
plutôt qu'après), ce que certains développeurs à Google a signalé très tôt. Cela faisait également partie de la raison pour laquelle la recommandation de YUI était de mettre des scripts à la fin dubody
, encore une fois dans la journée.la source
<body onload="doIt()>"
.load
événement se produit très tard dans le cycle de chargement de la page, il n'est presque jamais préférable d'attendre avant d'exécuter votre JavaScript. Mais oui, c'est une option. J'ai révisé la réponse pour 2020, d'ailleurs.document.addEventListener('DOMContentLoaded', function(){ //doyour stuff })
Vous pouvez exécuter du code javascript à tout moment. AFAIK il est exécuté au moment où le navigateur atteint la balise <script> où il se trouve. Mais vous ne pouvez pas accéder aux éléments qui ne sont pas encore chargés.
Donc, si vous avez besoin d'accéder à des éléments, vous devez attendre que le DOM soit chargé (cela ne signifie pas que la page entière est chargée, y compris les images et les choses. Il s'agit uniquement de la structure du document, qui est chargée beaucoup plus tôt, donc vous avez généralement gagné ne remarquez pas de retard), en utilisant l'
DOMContentLoaded
événement ou des fonctions comme$.ready
dans jQuery.la source