添加多个onload处理程序

Mik*_*ike 3 javascript event-handling onload

我有两个js文件,每个文件都有自己的window.onload处理程序。根据我将两个onload处理程序附加到窗口对象的方式,我在第二个处理程序上得到了不同的行为。

更具体地说,这是我的html文件:

<html>
<head>
 <title>Welcome to our site</title>
 <script type="text/javascript" src="script1.js"> </script>
 <script type="text/javascript" src="script2.js"> </script>
</head>
<body id="pageBody">
 <h2 align="center"> 
  <a href="http://www.whatever.com" id="redirect"> Wellcome to our site... c'mon in! </a> 
 </h2>
</body>
</html>
Run Code Online (Sandbox Code Playgroud)

它加载两个js文件,script1.js和script2.js。

这是这两个脚本的版本,它们导致(至少在我看来)意外的行为。

Script1.js:

window.onload = initAll1(); // attach first onload handler

function initAll1() {
 alert("initAll1");
 document.getElementById("redirect").onclick = foo; // attach an onclick handler
}

function foo() {
 alert("we are in foo"); 
 return false;
}
Run Code Online (Sandbox Code Playgroud)

Script2.js:

addOnloadHandler(initAll2); // with this we should attach a second onload handler

function initAll2() {
 alert("initAll2");
 if (linkHasOnclickHandler(document.getElementById("redirect"))) {
  alert("correct!"); 
 }
 else {
  alert("wrong!");
 }
}

function addOnloadHandler (newFunction) {
 var oldevent = window.onload;
 if (typeof oldevent == "function") {
  window.onload = function() {
      if (oldevent) {
          oldevent();
      }
   newFunction();
  };
 }
 else {
      window.onload = newFunction;
 }
}

function linkHasOnclickHandler() {
 var oldevent = document.getElementById("redirect").onclick;
 if (typeof oldevent == "function") {
  return true;
 }
 else {
  return false;
 }
}
Run Code Online (Sandbox Code Playgroud)

在Script2.js中,我尝试使用addOnloadHandler()函数以一种不错的非侵入性方式添加第二个onload处理程序。该函数不对是否已将任何onload处理程序附加到window对象进行任何假设。它是非侵入性的,因为它应该添加新的处理程序而不删除先前的处理程序。

事实是,在使用addOnloadHandler()加载时,initAll2()无法检测到document.getElementById(“ redirect”)已经附加了foo()作为onclick事件处理程序的事实(请参阅initAll1())。警报消息“错误!” 被触发,在我看来这是错误的行为。

当我忘记addOnloadHandler()并使用以下命令将两个onload处理程序附加到Script1.js中时:

window.onload = function () {initAll1(); initAll2();};
Run Code Online (Sandbox Code Playgroud)

然后一切都按预期工作,并且initAll2()启动“正确!” 警报消息。

addOnloadHandler()有什么问题吗?有人可以使它工作吗?我真的很想用它代替第二种方法。

谢谢!

Peb*_*bbl 5

万一将来人们发现这一点,并正在寻找一种方式来使用多个事件处理程序时,对象本身不支持addEventListenerattachEvent或者听者堆放一些其他形式的-也就是说,它是一个定制的对象,妥善执行。然后,您可以执行以下操作:

object.onload = (function(pre){
  return function(){
    pre && pre.apply(this,arguments);
    /// do what you need for your listener here
  }
})(object.onload);
Run Code Online (Sandbox Code Playgroud)

每次使用上面的代码时,都会将以前的onload侦听器作为参数传递,并且在触发新的侦听器时,它将首先运行旧的侦听器-意味着,如果您愿意,可以像这样堆叠许多侦听器。但是,仅在以上代码始终用于向对象添加侦听器的情况下,此方法才有效。如果用其他简单的方法覆盖了所有其他工作,那么所有的辛苦工作都将被撤消:

object.onload = function(){}
Run Code Online (Sandbox Code Playgroud)

作为对程序员的注释,如果您要实现库,插件或构造函数,则其他程序员可能会接管您的工作。请,请为多个事件侦听器编写功能。确实没有那么困难。


lon*_*day 3

您需要查看addEventListenerattachEvent,它们是您的addOnloadHandler.