我有两个js文件,每个文件都有自己的window.onload处理程序。根据我如何将两个onload处理程序附加到window对象,我在第二个处理程序上得到了不同的行为。
更具体地说,这是我的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>
它加载两个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;
}
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;
}
}
在Script2.js中,我尝试使用函数addOnloadHandler()以一种很好的非侵入方式添加第二个onload处理程序。此函数不会对是否已将任何onload处理程序附加到窗口对象进行任何假设。它是非侵入性的,因为它应该添加新的处理程序而不删除以前的处理程序。
问题在于,当加载addOnloadHandler()时,initAll2()无法检测到document.getElementById(“redirect”)已经将foo()作为onclick事件处理程序附加的事实(请参阅initAll1()) 。警告信息“错误!”被触发,这对我来说似乎是错误的行为。
当我忘记addOnloadHandler()并使用以下命令附加Script1.js中的两个onload处理程序时:
window.onload = function () {initAll1(); initAll2();};
然后一切都按预期工作,initAll2()启动“正确!”警报信息。
addOnloadHandler()有什么问题吗?任何人都可以使它工作吗?我真的想用它而不是第二种方法。
谢谢!
答案 0 :(得分:5)
以防未来的人发现这一点,并且当对象本身不支持addEventListener
,attachEvent
或其他形式的监听器堆叠时,正在寻找使用多个事件处理程序的方法 - 即它是一个定制的对象,执行得很糟糕。然后,您可以执行以下操作:
object.onload = (function(pre){
return function(){
pre && pre.apply(this,arguments);
/// do what you need for your listener here
}
})(object.onload);
每次使用上面的代码时,前一个onload
侦听器都作为参数传入,当您的新侦听器被触发时,它首先运行旧侦听器 - 这意味着您可以像这样堆叠许多侦听器,如果您愿意。但是,只有在上面的代码始终用于向对象添加侦听器时,这才会起作用。如果其他地方被简单的覆盖,那么你所有的努力都将被取消:
object.onload = function(){}
作为编码员的注释,如果要实现库,插件或构造函数,其他编码人员可能会接管您的工作。请为多个事件监听器编写代码。 这真的不那么难。
答案 1 :(得分:2)
您需要查看addEventListener
和attachEvent
,它们是addOnloadHandler
的原生实现。
答案 2 :(得分:1)
PPK对addEventListener的引用解释了这一点非常好:
答案 3 :(得分:1)
感谢您的回答!
我使用addEventListener和attachEvent重写了我的script2.js,如下所示:
//addOnloadHandler(initAll1); // it works only when uncommenting this
addOnloadHandler(initAll2);
function initAll2() {
alert("initAll2");
if (linkHasOnclickHandler(document.getElementById("redirect"))) {
alert("correct!");
}
else {
alert("wrong!");
}
}
function addOnloadHandler(newFunction) {
if (window.addEventListener) { // W3C standard
window.addEventListener('load', newFunction, false); // NB **not** 'onload'
}
else if (window.attachEvent) { // Microsoft
window.attachEvent('onload', newFunction);
}
}
function linkHasOnclickHandler(element) {
var oldevent = document.getElementById("redirect").onclick;
if (typeof oldevent == "function") {
return true;
}
else {
return false;
}
}
正如您所看到的,addOnloadHandler()已使用您提到的本机实现进行了重写。我没有触及script1.js。
结果代码仍然不起作用(即显示“错误!”警告消息)。它只有在我通过取消注释script2.js中的第一行代码来注册onload initAll1()处理程序两次时才有效。
显然,混合
window.onload = handler1;
和
window.addEventListener('load', handler2, false);
或
window.attachEvent('onload', handler2);
效果不好。
有没有办法解决这个问题并不意味着触及script1.js?
万一你想知道为什么我不想触摸script1.js,原因是我希望我的代码(script2.js)也可以在其他项目中重用,无论每个项目中哪个其他js文件使用。因此,它应该与script1.js中使用的每种可能的事件处理注册方法一起使用。
再次感谢您的帮助!