向 window.onload 添加两个函数

Add two functions to window.onload

提问人:AJJ 提问时间:5/22/2013 最后编辑:lulalalaAJJ 更新时间:12/21/2022 访问量:91285

问:

我的表单上有两个函数,但如果另一个处于活动状态,其中一个不起作用。这是我的代码:

window.onload = function(event) {
    var $input2 = document.getElementById('dec');
    var $input1 = document.getElementById('parenta');
    $input1.addEventListener('keyup', function() {
        $input2.value = $input1.value;
    });
}

window.onload=function(){
    document.getElementById('enable').onchange=function(){
        var txt = document.getElementById('gov1');
        if(this.checked) txt.disabled=false;
        else txt.disabled = true;
    };
};

我的意思是,当我的表单中同时拥有这两个函数时,第二个函数可以正常工作,但第一个函数将不起作用,如果取出第二个函数,第一个函数将正常工作,为什么会发生这种情况?是因为名字吗?

JavaScript 函数

评论

0赞 Adarsh 5/22/2013
为什么不将第二个函数中的功能添加到第一个函数中。或者从第一个调用第二个。
6赞 Ian 5/22/2013
你为什么不继续使用更好的方法来处理事件 - ?这样你就不会有这样的覆盖问题了addEventListener

答:

16赞 Leniel Maccaferri 5/22/2013 #1

不能将两个不同的函数分配给 。最后一个永远会赢。这就解释了为什么如果删除最后一个,第一个将开始按预期工作。window.onload

看起来您应该将第二个函数的代码合并到第一个函数中。

34赞 Janak 5/22/2013 #2

尝试将所有代码放入相同的 [并且只有 1] 个 onload 方法中!

 window.onload = function(){
        // All code comes here 
 }

评论

9赞 Marcelo 12/10/2016
我不能这样做,因为我的 onLoad 函数是动态回显的...... =/
0赞 Alexander Kucheryuk 2/15/2021
发生这种情况时,您可能希望重构代码,其中单个所谓的注册表获取所有函数,然后输出调用其他函数的单个函数
2赞 aaronman 5/22/2013 #3

当你把第二个函数放进去时,基本上你要做的就是替换一个值。正如之前有人所说,您可以将这两个函数合并为一个函数并设置为该函数。如果你感到困惑,可以这样想,如果你有一个对象,并且你做了,值将是 20 只是另一个对象window.onloadwindow.onloadobjectobject.value = 7; object.value = 20window

136赞 Khanh TO 5/22/2013 #4
window.addEventListener("load",function(event) {
    var $input2 = document.getElementById('dec');
    var $input1 = document.getElementById('parenta');
    $input1.addEventListener('keyup', function() {
        $input2.value = $input1.value;
    });
},false);

window.addEventListener("load",function(){
    document.getElementById('enable').onchange=function(){
        var txt = document.getElementById('gov1');
        if(this.checked) txt.disabled=false;
        else txt.disabled = true;
    };
},false);

文档在这里

请注意,此解决方案可能无法跨浏览器使用。我认为您需要依赖第 3 个库,例如 jquery$(document).ready

评论

4赞 5/22/2013
+1但是,他已经在他的代码中使用了,所以这个解决方案是公平的。addEventListener
1赞 Edward Chan JW 7/15/2018
+1 下面的答案,如扩展或IE特定,如果香草JS实现是有利的,可能会满足跨浏览器支持。如果 IE10 和其他浏览器支持 addEventListener,这意味着除了默认句柄之外,还可以添加更多的 EventListener:onload、onReadyStateChange、readystatechange,这不会影响使用第三方脚本,这很好且简单。希望我们以后不会有这种规格不匹配的问题。
1赞 cazort 12/15/2021
早在 2013 年写这个问题时,对跨浏览器支持的警告是有道理的,但现在在 2021 年,每个仍在使用中都不可忽视的浏览器都支持 .例如,我去年的数据显示,只有 0.19% 的用户使用 IE,其中只有 0.5% 的用户使用 IE <= 8(不支持此功能的最后一个版本)。因此,不到 100,000 名用户中的 1 名,而且只会随着时间的推移而减少。不值得担心。addEventListener
2赞 Xiaodan Mao 5/22/2013 #5

您不能将多个函数绑定到 window.onload,并期望所有这些函数都将被执行。另一种方法是使用 $(document).ready 而不是 window.onload,如果您已经在项目中使用了 jQuery。

10赞 elclanrs 5/22/2013 #6

因为你正在覆盖它。如果你想用它来做,你可以扩展以前的功能。这是一种方法:onload

Function.prototype.extend = function(fn) {
  var self = this;
  return function() {
    self.apply(this, arguments);
    fn.apply(this, arguments);
  };
};

window.onload = function() {
  console.log('foo');
};

window.onload = window.onload.extend(function() {
  console.log('bar');
});

// Logs "foo" and "bar"

演示:http://jsbin.com/akegut/1/edit

编辑:如果要扩展多个功能,可以使用以下功能:

Function.prototype.extend = function() {
  var fns = [this].concat([].slice.call(arguments));
  return function() {
    for (var i=0; i<fns.length; i++) {
      fns[i].apply(this, arguments);
    }
  };
};

window.onload = window.onload.extend(function(){...}, function(){...}, ...);

评论

1赞 Shayan 12/11/2019
仅修改您自己的原型。切勿修改标准 JavaScript 对象的原型。来源:w3schools.com/js/js_object_prototypes.asp
3赞 Marty 5/22/2013 #7

如果绝对必须触发单独的方法作为结果,则可以考虑设置一个将触发的回调函数队列。window.onload

它可能以最简单的形式显示如下:

var queue = [];
var loaded = false;

function enqueue(callback)
{
    if(!loaded) queue.push(callback);
    else callback();
}

window.onload = function()
{
    loaded = true;
    for(var i = 0; i < queue.length; i++)
    {
        queue[i]();
    }
}

并在您的案例中如此使用:

enqueue(function()
{
    var $input2 = document.getElementById('dec');
    var $input1 = document.getElementById('parenta');
    $input1.addEventListener('keyup', function()
    {
        $input2.value = $input1.value;

    });

});

enqueue(function()
{
    document.getElementById('enable').onchange=function()
    {
        var txt = document.getElementById('gov1');
        if(this.checked) txt.disabled=false;
        else txt.disabled = true;
    };

});
47赞 chad 5/22/2013 #8

如果由于某种原因无法组合这些函数,但您可以控制其中一个函数,则可以执行以下操作:

window.onload = function () {
    // first code here...
};

var prev_handler = window.onload;
window.onload = function () {
    if (prev_handler) {
        prev_handler();
    }
    // second code here...
};

以这种方式,两个处理程序都会被调用。

评论

1赞 Chris Kempen 10/20/2015
这就是我的做法。+1
2赞 joseantgv 9/27/2016
我收到错误:(Uncaught RangeError: Maximum call stack size exceeded
1赞 Brett 6/9/2017
我还遇到了堆栈溢出错误。我相信问题在于prev_handler最终指向window.onload函数本身,而window.onload函数本身又调用了调用window.onload函数的prev_handler。尝试创建一个双重委托,如 stackoverflow.com/questions/12213234/ 所示...
0赞 Alex Manea 2/28/2022
对我来说效果很好。感谢
3赞 SadhanaP 6/4/2013 #9

通过保留 2 window.onload(),执行最后一个块中的代码。

4赞 Tsonev 12/3/2013 #10

一段时间以来,我将上述解决方案与以下方面一起使用:

window.onload = function () {
    // first code here...
};

var prev_handler = window.onload;
window.onload = function () {
    if (prev_handler) {
        prev_handler();
    }
    // second code here...
};

但是,在某些情况下,它会导致IE抛出本文中描述的“堆栈溢出错误”:Internet Explorer上的“堆栈溢出在0行中”并在此处进行了很好的介绍

在阅读了所有建议的解决方案并牢记 jquery 不可用之后,这就是我想出的(通过一些浏览器兼容性检查进一步扩展了 Khanh TO 的解决方案)您认为这样的实现是否合适:

function bindEvent(el, eventName, eventHandler) {
            if (el.addEventListener){
                    el.addEventListener(eventName, eventHandler, false); 
                } else if (el.attachEvent){
                    el.attachEvent("on"+eventName, eventHandler);
                }
            }
      render_errors = function() {
      //do something
      }

      bindEvent(window, "load", render_errors);

      render_errors2 = function() {
      //do something2
      }

      bindEvent(window, "load", render_errors2);
13赞 rohit verma 4/10/2015 #11

window.addEventListener 在 IE 中不起作用,因此请使用 window.attachEvent

你可以做这样的事情

function fun1(){
    // do something
}

function fun2(){
    // do something
}


var addFunctionOnWindowLoad = function(callback){
      if(window.addEventListener){
          window.addEventListener('load',callback,false);
      }else{
          window.attachEvent('onload',callback);
      }
}

addFunctionOnWindowLoad(fun1);
addFunctionOnWindowLoad(fun2);

评论

1赞 Ahmed Taha 12/13/2021
在 chrome 上测试>工作正常
0赞 cazort 12/15/2021
在您的答案起作用大约 6+ 年后,它比您写它时更兼容。它在 IE >=9 中工作。在我最后一年的数据中,每 100,000 个用户中只有不到 1 个仍在使用 IE <=8,而且这个数字只会随着时间的推移而减少。所以我想说,从 2021 年开始,使用这种方法是安全的。
7赞 Sebastien Horin 2/19/2016 #12

如果使用 jQuery:

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

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

评论

0赞 Manish 6/24/2018
这似乎是一个不错的选择,但对我不起作用。
0赞 Zhuoer Dong 11/14/2018
你应该添加之后(我不能直接编辑,因为 SO 每次编辑至少要求 6 个字符))}
8赞 serkan 11/3/2016 #13

如果您无法访问旧的 window.onload,但仍想保留并添加另一个,那么方法如下:

       function addOnload(fun){
          var last = window.onload;
          window.onload = function(){
            if(last) last();
            fun();
          }
        } 

        addOnload(function(){
            console.log("1");
        });

        addOnload(function(){
            console.log("2");
        });
4赞 das Keks 2/27/2019 #14

为什么不从一个函数调用这两个函数呢?onload

function func1() {
    // code
}

function func2() {
    // code
}

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

评论

0赞 Frank Conijn - Support Ukraine 6/8/2022
这确实有效,并且是最简单的方法。无需 jQuery。我不知道OP是否可以应用它,但就我而言,这应该是公认的答案。
0赞 Mladen Adamovic 1/28/2020 #15

我不喜欢其他答案,并找到了另一种方法。

这可以通过此功能实现。
readyState 有 3 个选项加载、交互式和完整 https://developer.mozilla.org/en-US/docs/Web/API/Document/readyState

因此,此脚本将起作用:

<script>
  if (typeof whenDocReady === "function") {
    // already declared, do nothing
  } else {
    function whenDocReady(fn) {
      // see if DOM is already available
      if (document.readyState === "complete" || document.readyState === "interactive") {
        // call on next available tick
        setTimeout(fn, 1);
      } else {
        document.addEventListener("DOMContentLoaded", fn);
      }
    }
  }
</script>

定义此脚本后的用法:

<script>
whenDocReady(function() {
//do whatever stuff what you would do on window.onload
};
</script>

信用:https://stackoverflow.com/a/9899701/1537394

1赞 Adam 6/29/2021 #16

这对我有用

function first() {
    console.log(1234);
}

function second() {
    console.log(5678);
}

const windowOnload = window.onload = () => {
    first();
    second();
};

windowOnload();

安慰

1234

5678

0赞 user8481047 7/30/2021 #17

使用 Promises:

    function first(){
          console.log("first");
    }

    function second(){
          console.log("second");
    }
    
    isLoaded = new Promise((loaded)=>{ window.onload = loaded });
    isLoaded.then(first);
    isLoaded.then(second);