添加到window.onload事件中?

67

我想知道如何在已经分配了方法调用的window.onload事件中添加另一个方法调用。

假设在脚本的某处,我有以下赋值...

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

然后在脚本的后面,我有这个赋值语句

 window.onload = function(){ some_methods_2() };
目前只有some_methods_2会被调用。有没有办法在不取消some_methods_1的情况下添加到以前的window.onload回调中?(也不要在同一个函数块中包含some_methods_1()some_methods_2())。
我想这个问题并不是真正关于window.onload的,而是关于JavaScript的一般问题。我不想以这样的方式将某些内容分配给window.onload,以至于如果另一个开发人员在没有查看我的先前代码的情况下添加了使用window.onload的代码,他将禁用我的onload事件。
我也想知道同样的事情。
  $(document).ready()

在jQuery中,我如何在不破坏前面或后面的内容的情况下添加内容?


2
$(document).ready() 累加。如果有 jQuery,使用它。 - John Dvorak
5个回答

61

如果您正在使用jQuery,则无需进行任何特殊操作。通过$(document).ready()添加的处理程序不会相互覆盖,而是按顺序执行:

$(document).ready(func1)
...
$(document).ready(func2)
如果您没有使用 jQuery,您可以使用 Karaxuna 演示的 addEventListener,再加上适用于 IE<9 的 attachEvent
请注意,onload$(document).ready() 不等价 - 前者也会等待 CSS、图像等内容加载完成,而后者仅等待 DOM 树。现代浏览器(自 IE9 开始)支持文档上的 DOMContentLoaded 事件,它对应于 jQuery 的 ready 事件,但 IE<9 不支持。
if(window.addEventListener){
  window.addEventListener('load', func1)
}else{
  window.attachEvent('onload', func1)
}
...
if(window.addEventListener){
  window.addEventListener('load', func2)
}else{
  window.attachEvent('onload', func2)
}
如果没有这两个选项可用(例如,您没有处理DOM节点),您仍然可以这样做(我使用onload作为示例,但其他选项也适用于onload):

如果没有可用的这两个选项(例如,您没有处理DOM节点),您仍然可以这样做(我以onload为例,但其他选项也是适用于onload):

var oldOnload1=window.onload;
window.onload=function(){
  oldOnload1 && oldOnload1();
  func1();
}
...
var oldOnload2=window.onload;
window.onload=function(){
  oldOnload2 && oldOnload2();
  func2();
}

或者,为了避免污染全局命名空间(以及可能遇到命名空间冲突),可以使用导入/导出IIFE模式:

window.onload=(function(oldLoad){
  return function(){
    oldLoad && oldLoad();
    func1();
  }
})(window.onload)
...
window.onload=(function(oldLoad){
  return function(){
    oldLoad && oldLoad();
    func2();
  }
})(window.onload)

2
你的意思是 "document.attachEvent('onload'...)",而不是 'load'。 ;) - James Wilkins
你不应该使用document.addEventListener("load")(在我的版本的Firefox上无效),而是要使用window.addEventListener("load")。请参阅https://dev59.com/WmQn5IYBdhLWcg3w_LXx。 - Jeremy Salwen
2
@JeremySalwen 找到了更好的来源:https://html.spec.whatwg.org/multipage/indices.html#event-load。已经更正。 - John Dvorak

50

你可以使用attachEvent(ie8)和addEventListener来替代

addEvent(window, 'load', function(){ some_methods_1() });
addEvent(window, 'load', function(){ some_methods_2() });

function addEvent(element, eventName, fn) {
    if (element.addEventListener)
        element.addEventListener(eventName, fn, false);
    else if (element.attachEvent)
        element.attachEvent('on' + eventName, fn);
}

那么为了使其跨浏览器兼容,我应该同时使用两者吗? 另外,如果在脚本中先使用addEventListener,然后在window.onload上附加回调函数,那么之前使用addEventListener分配的内容会被取消吗? - pepper

9
基本上有两种方法:
1. 存储window.onload的前一个值,以便您的代码在执行之前或之后调用先前的处理程序。 2. 使用addEventListener方法(当然微软不喜欢它,并要求您使用另一个不同的名称)。
第二种方法会使您更加安全,如果另一个脚本想要使用window.onload并且没有考虑合作,但Javascript的主要假设是所有脚本都像您正在尝试做的那样合作。
请注意,一个不设计与其他未知脚本一起工作的坏脚本将始终能够破坏页面,例如通过搞乱原型、污染全局命名空间或破坏dom。

太棒了!那jQuery的$(document).ready()或bind()怎么样? - pepper
你知道jQuery只是JavaScript吗?我没有检查过,但我猜它可能会使用(2)(如果可用)或(1)(对于旧浏览器)。 - 6502
当然可以,我只是问一下因为$(document).ready()和window.onload有一点不同。"ready"事件发生在HTML文档加载完成后,而"onload"事件则是在所有内容(例如图片)也加载完成后发生的。 - pepper

5

这可能不是常见的选项,但有时脚本最终会被分成各个部分进行分发,在这种情况下,我发现这是一个快速的解决办法。

if(window.onload != null){var f1 = window.onload;}
window.onload=function(){
    //do something

    if(f1!=null){f1();}
}

然后在其他地方...

if(window.onload != null){var f2 = window.onload;}
window.onload=function(){
    //do something else

    if(f2!=null){f2();}
}

这将更新 onload 函数并根据需要进行链式处理。

4

一个纯JavaScript(不使用jQuery)的方法,它不会覆盖现有的onload事件,而是添加到它上面的方法如下:

window.addEventListener('load', function() {
    // do your things here
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接