我正在执行一个外部脚本,使用<脚本>内<头>。
现在,由于脚本在页面加载之前执行,我不能访问<body>等。我想在文档被“加载”(HTML完全下载并在ram中)后执行一些JavaScript。是否有任何事件,我可以挂钩到当我的脚本执行,这将在页面加载触发?
我正在执行一个外部脚本,使用<脚本>内<头>。
现在,由于脚本在页面加载之前执行,我不能访问<body>等。我想在文档被“加载”(HTML完全下载并在ram中)后执行一些JavaScript。是否有任何事件,我可以挂钩到当我的脚本执行,这将在页面加载触发?
当前回答
在合适的时机触发脚本
A quick overview on how to load / run the script at the moment in which they intend to be loaded / executed.使用“推迟”
<script src="script.js" defer></script>
使用defer将触发domInteractive (document. doc .)readyState = "interactive"),就在"DOMContentLoaded"事件触发之前。如果你需要在所有资源(图像,脚本)加载后执行脚本,请使用“load”事件或目标文档之一。请求状态。继续往下阅读,了解有关这些事件/状态的更多信息,以及与脚本获取和执行计时相对应的async和defer属性。
此布尔属性被设置为向浏览器指示脚本 意味着在解析文档之后执行,但在解析之前 发射DOMContentLoaded。内 带有defer属性的脚本将阻止DOMContentLoaded 事件,直到脚本加载并完成求值。
资源:https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script属性
*请参阅底部的图片以了解羽毛的解释。
事件监听器-请记住页面的加载有多个事件:
“DOMContentLoaded”
当初始HTML文档完全加载和解析完毕时,无需等待样式表、图像和子帧完成加载,就会触发此事件。在这个阶段,您可以基于用户设备或带宽速度以编程方式优化图像和CSS的加载。 DOM加载后执行(在图像和CSS之前):
document.addEventListener("DOMContentLoaded", function(){
//....
});
注意:同步JavaScript暂停DOM的解析。 如果希望在用户请求页面后尽可能快地解析DOM,可以将JavaScript转换为异步并优化样式表的加载
“负载”
A very different event, **load**, should only be used to detect a *fully-loaded page*. It is an incredibly popular mistake to use load where DOMContentLoaded would be much more appropriate, so be cautious.在所有内容加载并解析后执行:
document.addEventListener("load", function(){
// ....
});
MDN资源: https://developer.mozilla.org/en-US/docs/Web/Events/DOMContentLoaded https://developer.mozilla.org/en-US/docs/Web/Events/load
所有事件的MDN列表: https://developer.mozilla.org/en-US/docs/Web/Events
事件监听器与readyStates -替代解决方案(readystatechange):
You can also track document.readystatechange states to trigger script execution.// Place in header (do not use async or defer)
document.addEventListener('readystatechange', event => {
switch (document.readyState) {
case "loading":
console.log("document.readyState: ", document.readyState,
`- The document is still loading.`
);
break;
case "interactive":
console.log("document.readyState: ", document.readyState,
`- The document has finished loading DOM. `,
`- "DOMContentLoaded" event`
);
break;
case "complete":
console.log("document.readyState: ", document.readyState,
`- The page DOM with Sub-resources are now fully loaded. `,
`- "load" event`
);
break;
}
});
MDN资源:https://developer.mozilla.org/en-US/docs/Web/API/Document/readyState
在哪里放置你的脚本(有&没有异步/延迟)?
This is also very important to know where to place your script and how it positions in HTML as well as parameters like defer and async will affects script fetching, execution and HTML blocking.如果你的脚本使用async或defer,请阅读:https://flaviocopes.com/javascript-async-defer/
如果以上几点都还为时过早……
如果你需要你的脚本在其他脚本运行之后运行,包括那些计划在最后运行的脚本(例如,那些计划在“load”事件中运行的脚本),该怎么办?参见“运行JavaScript”窗口。Onload脚本是否已完成?
如果您需要确保您的脚本在其他脚本之后运行,而不管它何时运行,该怎么办?以上问题的答案也涵盖了这一点。
其他回答
如果脚本是在文档的<head>中加载的,那么可以在script标记中使用defer属性。
例子:
<script src="demo_defer.js" defer></script>
从https://developer.mozilla.org:
推迟 此布尔属性被设置为向浏览器指示脚本 意味着在解析文档之后执行,但在解析之前 发射DOMContentLoaded。内 如果src 属性不存在(即对于内联脚本),在这种情况下它会 没有效果。 为实现动态插入脚本使用的类似效果 异步= false。具有defer属性的脚本将在 它们在文档中出现的顺序。
比较
在下面的片段中,我收集选择的方法并显示它们的序列。讲话
the document.onload (X) is not supported by any modern browser (event is never fired) if you use <body onload="bodyOnLoad()"> (F) and at the same time window.onload (E) then only first one will be executed (because it override second one) event handler given in <body onload="..."> (F) is wrapped by additional onload function document.onreadystatechange (D) not override document .addEventListener('readystatechange'...) (C) probably cecasue onXYZevent-like methods are independent than addEventListener queues (which allows add multiple listeners). Probably nothing happens between execution this two handlers. all scripts write their timestamp in console - but scripts which also have access to div write their timestamps also in body (click "Full Page" link after script execution to see it). solutions readystatechange (C,D) are executed multiple times by browser but for different document states: loading - the document is loading (no fired in snippet) interactive - the document is parsed, fired before DOMContentLoaded complete - the document and resources are loaded, fired before body/window onload
<html> <head> <script> // solution A console.log(`[timestamp: ${Date.now()}] A: Head script`); // solution B document.addEventListener("DOMContentLoaded", () => { print(`[timestamp: ${Date.now()}] B: DOMContentLoaded`); }); // solution C document.addEventListener('readystatechange', () => { print(`[timestamp: ${Date.now()}] C: ReadyState: ${document.readyState}`); }); // solution D document.onreadystatechange = s=> {print(`[timestamp: ${Date.now()}] D: document.onreadystatechange ReadyState: ${document.readyState}`)}; // solution E (never executed) window.onload = () => { print(`E: <body onload="..."> override this handler`); }; // solution F function bodyOnLoad() { print(`[timestamp: ${Date.now()}] F: <body onload='...'>`); infoAboutOnLoad(); // additional info } // solution X document.onload = () => {print(`document.onload is never fired`)}; // HELPERS function print(txt) { console.log(txt); if(mydiv) mydiv.innerHTML += txt.replace('<','<').replace('>','>') + '<br>'; } function infoAboutOnLoad() { console.log("window.onload (after override):", (''+document.body.onload).replace(/\s+/g,' ')); console.log(`body.onload==window.onload --> ${document.body.onload==window.onload}`); } console.log("window.onload (before override):", (''+document.body.onload).replace(/\s+/g,' ')); </script> </head> <body onload="bodyOnLoad()"> <div id="mydiv"></div> <!-- this script must te at the bottom of <body> --> <script> // solution G print(`[timestamp: ${Date.now()}] G: <body> bottom script`); </script> </body> </html>
只需定义<body onload=" function ()>,它将在页面加载后被调用。脚本中的代码被function(){}括起来。
看钩文件。jQuery $(document).load(…)
这是一个基于延迟js加载的脚本,在页面加载后,
<script type="text/javascript">
function downloadJSAtOnload() {
var element = document.createElement("script");
element.src = "deferredfunctions.js";
document.body.appendChild(element);
}
if (window.addEventListener)
window.addEventListener("load", downloadJSAtOnload, false);
else if (window.attachEvent)
window.attachEvent("onload", downloadJSAtOnload);
else window.onload = downloadJSAtOnload;
</script>
我该把它放在哪里?
将代码粘贴到</body>标记之前(靠近HTML文件的底部)。
它能做什么?
此代码表示等待整个文档加载,然后加载 外部文件deferredfunctions.js。
这是上面代码的一个例子- JS的延迟渲染
我写这个基于延迟加载javascript页面速度谷歌的概念,也从这篇文章延迟加载javascript