如何让JavaScript在页面加载后执行?

How to make JavaScript execute after page load?

提问人:Robin Rodricks 提问时间:5/1/2009 最后编辑:Kamil KiełczewskiRobin Rodricks 更新时间:12/30/2022 访问量:2339797

问:

我正在执行一个外部脚本,使用内部.<script><head>

现在,由于脚本在页面加载之前执行,因此我无法访问 ,等等。我想在文档“加载”后执行一些 JavaScript(HTML 完全下载并在 RAM 中)。当我的脚本执行时,是否有任何事件可以挂接到,这些事件将在页面加载时触发?<body>

JavaScript HTML DOM 事件 页面加载

评论

0赞 Inigo 12/30/2022
对于“在页面加载后立即”仍然为时过早的情况:在所有 window.onload 脚本完成后运行 JavaScript?

答:

23赞 Daniel A. White 5/1/2009 #1

看看钩子或jQuery。document.onload$(document).load(...)

评论

0赞 Robin Rodricks 5/1/2009
这个事件可靠吗?(跨浏览器..IE6+、FF2+等)
1赞 Daniel A. White 5/1/2009
是的,这是跨浏览器的标准 DOM。
20赞 Peter Bailey 5/1/2009
实际上更标准的是 window.onload,而不是 document.onload。AFAIK公司
1赞 Ωmega 4/16/2022
是在加载所有资源(如字体和图像)并正确直观更新之前还是之后调用?onload
7赞 Norbert Hartl 5/1/2009 #2

只需定义将在加载页面后调用的内容即可。脚本中的代码比 括起来。<body onload="aFunction()">aFunction() { }

1188赞 marcgg 5/1/2009 #3

这些解决方案将起作用:

如评论中所述,使用 defer

<script src="deferMe.js" defer></script>

<body onload="script();">

document.onload = function ...

甚至

window.onload = function ...

请注意,最后一个选项是更好的选择,因为它不显眼并且被认为更标准

评论

9赞 Mentoliptus 8/16/2011
<body onload=“script();” 和有什么不一样?> 和 document.onload=function ... ?
17赞 marcgg 9/5/2011
@mentoliptus:不突兀 en.wikipedia.org/wiki/Unobtrusive_JavaScriptdocument.onload=
29赞 marcgg 1/29/2014
@gerdi OP 没有提到任何关于 jQuery 的内容。我在回答中还给出了一个不显眼的选择。
7赞 spottedmahn 7/29/2017
document.onload 对我不起作用。我发现这篇文章有同样的问题 stackoverflow.com/questions/5135638/...。似乎 document.onload 不是一个选项。
8赞 ToolmakerSteve 5/1/2019
所有这些选项都比必要的要晚得多,因为目标是在 DOM 准备好作后运行 javascript。对于这个目标,有两个更好的选择:1)在head中使用javascript链接的属性。2) 将任何访问 DOM 的 javascript 移动到页面底部,紧挨着 .defer</body>
138赞 Nordes 5/1/2009 #4

您可以在正文中放置一个“onload”属性

...<body onload="myFunction()">...

或者,如果你使用的是jQuery,你可以做

$(document).ready(function(){ /*code here*/ }) 

or 

$(window).load(function(){ /*code here*/ })

我希望它能回答你的问题。

请注意,$(window).load 将在文档呈现到您的页面上后执行。

1赞 Iain 5/1/2009 #5

正如 Daniel 所说,你可以使用 document.onload。

各种 javascript 框架(jQuery、Mootools 等)都使用自定义事件“domready”,我想这一定更有效。如果你正在使用 javascript 进行开发,我强烈建议你利用一个框架,它们可以大大提高你的生产力。

211赞 chaos 5/1/2009 #6

合理可移植的非框架方式,让您的脚本将函数设置为在加载时运行:

if(window.attachEvent) {
    window.attachEvent('onload', yourFunctionName);
} else {
    if(window.onload) {
        var curronload = window.onload;
        var newonload = function(evt) {
            curronload(evt);
            yourFunctionName(evt);
        };
        window.onload = newonload;
    } else {
        window.onload = yourFunctionName;
    }
}

评论

13赞 Grant Wagner 5/1/2009
+1 几乎完全符合我 6 个月前的想法。如果您无法控制的其他框架和代码正在添加 onload 事件,并且您也希望在不清除其他 onload 事件的情况下添加此类代码,则可能需要这样的代码。我将我的实现作为一个函数包含在内,它需要 var newonload = function(evt) { curronload(evt); newOnload(evt); } 因为出于某种原因,我使用的框架需要将一个事件传递给 onload 事件。
6赞 Grant Wagner 5/5/2009
我刚刚在测试中发现,编写的代码会导致处理程序在附加 accesschEvent() 时以未定义的顺序触发。如果 order-of-handler-execution 很重要,则可能需要省略 window.attachEvent 分支。
0赞 Clay Nichols 6/9/2017
所以这会将此函数添加为附加函数以运行 OnLoad,对吗?(而不是替换现有的 onload 事件)
0赞 chaos 6/10/2017
@ClayNichols:没错。
2赞 Renan 11/26/2017
很好的解决方案,但现在已经过时了:developer.mozilla.org/en-US/docs/Web/API/EventTarget/......
1赞 Valentin Jacquemin 5/1/2009 #7

使用 YUI 库(我喜欢它):

YAHOO.util.Event.onDOMReady(function(){
    //your code
});

便携且美观!但是,如果您不将 YUI 用于其他东西(请参阅其文档),我会说不值得使用它。

注意:要使用此代码,您需要导入 2 个脚本

<script type="text/javascript" src="http://yui.yahooapis.com/2.7.0/build/yahoo/yahoo-min.js" ></script>
<script type="text/javascript" src="http://yui.yahooapis.com/2.7.0/build/event/event-min.js" ></script>
35赞 Lucky 2/5/2013 #8

下面是一个基于页面加载后延迟 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>

我该把它放在哪里?

将代码粘贴到 HTML 中标记的前面(靠近 HTML 文件的底部)。</body>

它有什么作用?

这段代码说等待整个文档加载完毕,然后加载 外部文件。deferredfunctions.js

下面是上述代码的示例 - JS 的延迟渲染

我写这篇文章是基于 javascript pagespeed google 概念的延迟加载,也来源于这篇文章延迟加载 javascript

评论

0赞 Lucas Vazquez 12/23/2021
我认为这个解决方案,结合用户(stackoverflow.com/a/807997/10712525)的答案,将是你能做的最好的事情。chaos
9赞 Benjamin Crouzier 3/7/2013 #9

如果您使用的是 jQuery,

$(function() {...});

相当于

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

或其他简手:

$().ready(function () { })

请参阅 JQuery $function() 在什么事件上触发?https://api.jquery.com/ready/

11赞 Aamir Shahzad 3/26/2013 #10

工作小提琴<body onload="myFunction()">

<!DOCTYPE html>
<html>
 <head>
  <script type="text/javascript">
   function myFunction(){
    alert("Page is loaded");
   }
  </script>
 </head>

 <body onload="myFunction()">
  <h1>Hello World!</h1>
 </body>    
</html>
4赞 Akarsh Satija 4/29/2013 #11
<body onload="myFunction()">

此代码运行良好。

但是方法有各种依赖关系。所以它可能不会一直有效。window.onload

14赞 Juniper Jones 7/21/2013 #12

我发现有时在更复杂的页面上,并非所有元素在触发 window.onload 时都已加载。如果是这种情况,请在函数延迟片刻之前添加 setTimeout。它并不优雅,但它是一个简单的技巧,渲染得很好。

window.onload = function(){ doSomethingCool(); };

成为。。。

window.onload = function(){ setTimeout( function(){ doSomethingCool(); }, 1000); };
81赞 Daniel Price 1/10/2014 #13

如果脚本加载到文档中,则可以在脚本标记中使用该属性。<head>defer

例:

<script src="demo_defer.js" defer></script>

https://developer.mozilla.org

推迟

此 Boolean 属性设置为向浏览器指示脚本 在解析文档之后执行,但在解析文档之前执行 触发 DOMContentLoaded。

如果 src 属性不存在(即对于内联脚本),在这种情况下,它会 没有效果。

要实现动态插入脚本的类似效果,请使用 async=false 代替。具有 defer 属性的脚本将在 它们在文档中出现的顺序。

评论

1赞 sarkiroka 5/11/2020
我喜欢这个解决方案,因为不需要任何 javascript 代码,只需要一个 html 属性 <3
0赞 Akansh 10/20/2020
这从根本上是错误的。延迟不会阻止在页面加载后执行。defer 和 async 脚本都是在页面加载之前加载的,而是改进了“domInteraction”时间。
2赞 Daniel Price 2/1/2021
@Akansh OP 只是想要一种方法来确保 DOM 在脚本执行之前已经加载。Defer 这样做,它实际上是写在我在答案中分享的文档片段中。
0赞 1.21 gigawatts 8/19/2021
看起来您可以使用 async false 在页面加载后加载内联脚本?“要实现动态插入脚本的类似效果,请改用 async=false。- 此 Boolean 属性设置为向浏览器指示脚本应在解析文档之后但在触发 DOMContentLoaded 之前执行。
8赞 Arthur Tsidkilov 9/11/2014 #14
document.onreadystatechange = function(){
     if(document.readyState === 'complete'){
         /*code here*/
     }
}

看这里:http://msdn.microsoft.com/en-us/library/ie/ms536957(v=vs.85).aspx

评论

3赞 colm.anseo 3/27/2015
单行: document.onload = function() { ... }
11赞 Frankey 9/12/2014 #15
<script type="text/javascript">
  function downloadJSAtOnload() {
   var element = document.createElement("script");
   element.src = "defer.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>

http://www.feedthebot.com/pagespeed/defer-loading-javascript.html

0赞 Kalidass 3/30/2015 #16

我建议将属性用于脚本标签,帮助您在页面加载后加载外部脚本asnyc

<script type="text/javascript" src="a.js" async></script>
<script type="text/javascript" src="b.js" async></script>

评论

10赞 jk7 4/15/2015
根据 w3schools 的说法,如果存在异步:脚本与页面的其余部分异步执行(脚本将在页面继续解析时执行)。也许你的意思是,就像@Daniel普莱斯提到的那样?defer
0赞 Vô Vị 9/29/2015 #17

<script type="text/javascript">
$(window).bind("load", function() { 

// your javascript event here

});
</script>

评论

6赞 Chiptus 9/5/2018
这个答案取决于jquery
3赞 user5642061 12/12/2015 #18

有一个非常好的文档关于如何检测文档是否已使用 Javascript 或 Jquery 加载。

使用原生 Javascript 可以实现这一点

if (document.readyState === "complete") {
 init();
 }

这也可以在间隔内完成

var interval = setInterval(function() {
    if(document.readyState === 'complete') {
        clearInterval(interval);
        init();
    }    
}, 100);

例如,Mozilla

switch (document.readyState) {
  case "loading":
    // The document is still loading.
    break;
  case "interactive":
    // The document has finished loading. We can now access the DOM elements.
    var span = document.createElement("span");
    span.textContent = "A <span> element.";
    document.body.appendChild(span);
    break;
  case "complete":
    // The page is fully loaded.
    console.log("Page is loaded completely");
    break;
}

使用 Jquery 仅检查 DOM 是否准备就绪

// A $( document ).ready() block.
$( document ).ready(function() {
    console.log( "ready!" );
});

要检查是否加载了所有资源,请使用 window.load

 $( window ).load(function() {
        console.log( "window loaded" );
    });
479赞 DevWL 3/19/2016 #19

在适当的时候触发脚本

关于如何在打算加载/执行脚本的那一刻加载/运行脚本的快速概述。

使用“defer”

<script src="script.js" defer></script>

使用 defer 将在 domInteractive (document.readyState = “interactive”) 之后和触发 “DOMContentLoaded” 事件之前触发。如果需要在加载所有资源(图像、脚本)后执行脚本,请使用 “load” 事件或以 document.readyState 状态之一为目标。请继续阅读,了解有关这些事件/状态的更多信息,以及与脚本获取和执行计时相对应的 async 和 defer 属性。

此 Boolean 属性设置为向浏览器指示脚本 在解析文档之后执行,但在解析文档之前执行 触发 DOMContentLoaded。

具有 defer 属性的脚本将阻止 DOMContentLoaded 事件从触发到脚本加载并完成计算。

资源: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script#attributes

* 有关羽毛说明,请参阅底部的图片。

事件侦听器 - 请记住,加载页面时有多个事件:

“DOMContentLoaded”

初始 HTML 文档完全加载和解析时,将触发此事件,而无需等待样式表、图像和子帧完成加载。在此阶段,您可以根据用户设备或带宽速度以编程方式优化图像和 CSS 的加载。

加载 DOM 后执行(在图像和 CSS 之前):

document.addEventListener("DOMContentLoaded", function(){
    //....
});

注意:同步 JavaScript 会暂停 DOM 的解析。 如果您希望在用户请求页面后尽快解析 DOM,您可以将 JavaScript 异步化优化样式表的加载

“加载”

一个非常不同的事件 **load** 应该只用于检测 *完全加载的页面*。在 DOMContentLoaded 更合适的地方使用 load 是一个非常普遍的错误,因此请谨慎。

在加载并解析所有内容后执行:

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):

您还可以跟踪 document.readystatechange 状态以触发脚本执行。
// 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

将脚本放在哪里(带 & 不带异步/延迟)?

了解脚本的放置位置以及它在 HTML 中的位置以及 defer 和 async 等参数会影响脚本获取、执行和 HTML 阻止也非常重要。

* 在下面的图片中,黄色标签“Ready”表示结束加载 HTML DOM 的时刻。然后它触发: document.readyState = “interactive” >>> DOMContentLoaded 事件>>>延迟脚本(它是连续的);

enter image description here

enter image description here

enter image description here

enter image description here

如果您的脚本使用 asyncdefer,请阅读以下内容: https://flaviocopes.com/javascript-async-defer/

如果以上所有几点都还为时过早......

如果您需要在其他脚本运行运行脚本,包括那些计划在最后运行的脚本(例如,那些为“加载”事件计划运行的脚本),该怎么办?请参阅在所有 window.onload 脚本完成后运行 JavaScript?

如果您需要确保脚本在其他脚本之后运行,而不管它何时运行,该怎么办?上述问题的答案也涵盖了这一点。

评论

1赞 arodebaugh 7/18/2017
@Peter很确定,如果它位于 JavaScript 文件的底部,那么它可能最好是独立的,这样它就可以最后执行
4赞 tfont 1/24/2019
这是最完整的答案。onload 是之后的,但人们一开始并没有意识到这一点。
4赞 ToolmakerSteve 5/1/2019
Re asynchronous javascript:澄清一下,对于不会立即运行的脚本,有两种选择。其中,defer 通常比 async 更可取——因为 defer 不会中断 html 解析/渲染——当它运行时,DOM 可以保证准备就绪。使用 defer 和 async 高效加载 JavaScript
2赞 wkille 1/24/2020
+1 我试着认为我的脚本会等到所有内容都完全下载后再运行,但它实际上的行为似乎是这样的,而实际上确实在等待所有内容完全下载。我本来以为这应该等同于而不是??我在 Chrome 和 FF 中得到了相同的结果。window.onload = ...window.onloaddocument.addEventListener("DOMContentLoaded", ...window.addEventListener("load", ...window.onloadwindow.addEventListener("load", ...document.addEventListener("DOMContentLoaded", ...
0赞 RayLoveless 3/5/2022
@DevWL,我想你的意思是“推迟”......因为“async”仍然可以在所有 HTML 加载之前执行。
3赞 Harish Kumar 12/21/2017 #20

将此代码与jQuery库一起使用,这将完全正常工作。

$(window).bind("load", function() { 

  // your javascript event

});

评论

1赞 Mathews Sunny 12/21/2017
在此处添加一些描述
3赞 Zach Reynolds 3/8/2018 #21
$(window).on("load", function(){ ... });

.ready() 最适合我。

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

.load() 可以工作,但它不会等到页面加载。

jQuery(window).load(function () { ... });

对我不起作用,破坏了下一个内联脚本。我还使用 jQuery 3.2.1 以及其他一些 jQuery 分支。

为了隐藏我的网站加载叠加层,我使用以下内容:

<script>
$(window).on("load", function(){
$('.loading-page').delay(3000).fadeOut(250);
});
</script>
23赞 T.Todua 4/7/2020 #22

JavaScript的

document.addEventListener('readystatechange', event => { 

    // When HTML/DOM elements are ready:
    if (event.target.readyState === "interactive") {   //does same as:  ..addEventListener("DOMContentLoaded"..
        alert("hi 1");
    }

    // When window loaded ( external resources are loaded too- `css`,`src`, etc...) 
    if (event.target.readyState === "complete") {
        alert("hi 2");
    }
});

jQuery也一样:

$(document).ready(function() {   //same as: $(function() { 
     alert("hi 1");
});

$(window).load(function() {
     alert("hi 2");
});





注意: - 不要使用以下标记(因为它会覆盖其他同类声明):

document.onreadystatechange = ...
4赞 Kamil Kiełczewski 6/18/2020 #23

比较

在下面的片段中,我收集了选择的方法并显示了它们的顺序。言论

  • 任何现代浏览器都不支持 (X) (事件从不触发document.onload)
  • 如果同时使用 (F) 和 (E),则只会执行第一个(因为它覆盖了第二个)<body onload="bodyOnLoad()">window.onload
  • (F) 中给出的事件处理程序由附加函数包装<body onload="...">onload
  • document.onreadystatechange(D) 不覆盖 (C) 可能 cecasue 方法与队列无关(允许添加多个侦听器)。在执行这两个处理程序之间可能没有任何反应。document .addEventListener('readystatechange'...)onXYZevent-likeaddEventListener
  • 所有脚本都在控制台中写入其时间戳 - 但脚本也可以在正文中写入其时间戳(在脚本执行后单击“整页”链接以查看它)。div
  • 解决方案 (C,D) 由浏览器执行多次,但针对不同的文档状态:readystatechange
    • loading - 文档正在加载(代码段中未触发)
    • 交互式 - 文档被解析,触发之前DOMContentLoaded
    • 完成 - 文档和资源已加载,在之前触发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('<','&lt;').replace('>','&gt;') + '<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>

1赞 saber tabatabaee yazdi 3/30/2021 #24

我可以通过此代码捕获页面加载

<script>
console.log("logger saber");

window.onload = (event) => {
  console.log('page is fully loaded');
document.getElementById("tafahomNameId_78ec7c44-beab-40de-9326-095f474519f4_$LookupField").value = 1;;
};

</script>
2赞 Camel Djoulako 4/2/2021 #25

您可以在特定脚本文件上编写函数,并使用 onload 属性将其调用到 body 元素中。

示例:

<script>
  afterPageLoad() {
   //your code here
}
</script>

现在使用 script 标签将脚本调用到 html 页面中:

<script src="afterload.js"></script>

进入你的身体元素;添加 onload 属性,如下所示:

<body onload="afterPageLoad();">

评论

2赞 Yunnosch 6/17/2021
请重新考虑您的回滚,撤消了有用的编辑。让其他用户提高您帖子的可读性应该被认为是一件好事。