【问题标题】:Add two functions to window.onload在 window.onload 中添加两个函数
【发布时间】:2013-05-16 23:56:45
【问题描述】:

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

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;
    };
};

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

【问题讨论】:

  • 你为什么不把第二个函数中的功能添加到第一个函数中。或者从第一个调用第二个。
  • 为什么不继续使用更好的事件处理方式——addEventListener?那么你就不会有这样的覆盖问题

标签: javascript function


【解决方案1】:
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);

文档是here

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

【讨论】:

  • +1 但是,他的代码中已经使用了addEventListener,所以这个解决方案是公平的。
  • +1 如果 vanilla JS 实现更受青睐,下面的答案(如扩展或 IE 特定)可能会满足跨浏览器支持。如果IE10和其他浏览器支持addEventListener,就是在默认句柄的基础上增加更多的EventListener:onload、onReadyStateChange、readystatechange,这很好也很简单,使用第三方脚本不会影响。希望以后不会再出现这个规范不匹配的问题。
  • 在 2013 年编写此问题时,对跨浏览器支持的谨慎是有道理的,但现在到 2021 年,每个仍在不可忽略的使用中的浏览器都支持 addEventListener。例如,我去年的数据显示只有 0.19% 的用户使用 IE,其中只有 0.5% 使用 IE
【解决方案2】:

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

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

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

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

【讨论】:

  • 我就是这样做的。 +1
  • 我收到Uncaught RangeError: Maximum call stack size exceeded 错误:(
  • 我也遇到了堆栈溢出错误。我认为问题在于 prev_handler 最终指向了 window.onload 函数本身,该函数本身又调用了调用 window.onload 函数的 prev_handler。尝试制作一个双重委托,如stackoverflow.com/questions/12213234/… 所示
【解决方案3】:

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

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

【讨论】:

  • 我不能这样做,因为我的 onLoad 函数是动态回显的... =/
  • 发生这种情况时,您可能需要重构代码,其中一个所谓的注册表获取所有函数,然后输出一个调用其他函数的单个函数
【解决方案4】:

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

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

【讨论】:

    【解决方案5】:

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

    【讨论】:

    • 工作正常 > 在 chrome 上测试
    • 在您的答案生效大约 6 年后,它比您编写它时更兼容。它适用于 IE >=9。在我去年的数据中,仍然在使用 IE
    【解决方案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(){...}, ...);
    

    【讨论】:

    【解决方案7】:

    如果您无法访问旧的 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");
            });
    

    【讨论】:

      【解决方案8】:

      简单使用(jQuery):

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

      【讨论】:

      • 这似乎是一个不错的选择,但对我不起作用。
      • 你应该在}之后添加)(我不能直接编辑,因为每次编辑要求至少6个字符)
      【解决方案9】:

      一段时间以来,我将上述解决方案用于:

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

      但是,在某些情况下,它会导致 IE 抛出本文所述的“堆栈溢出错误”: "Stack overflow in line 0" on Internet Explorer 并写了一篇很好的文章here

      在阅读了所有建议的解决方案并记住 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);
      

      【讨论】:

        【解决方案10】:

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

        【讨论】:

          【解决方案11】:

          为什么不直接从一个onload-function 调用这两个函数?

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

          【讨论】:

            【解决方案12】:

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

            【讨论】:

              【解决方案13】:

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

              【讨论】:

                【解决方案14】:

                如果您绝对必须触发单独的方法作为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;
                    };
                
                });
                

                【讨论】:

                  【解决方案15】:

                  这对我有用

                  function first() {
                      console.log(1234);
                  }
                  
                  function second() {
                      console.log(5678);
                  }
                  
                  const windowOnload = window.onload = () => {
                      first();
                      second();
                  };
                  
                  windowOnload();
                  

                  控制台

                  1234

                  5678

                  【讨论】:

                    【解决方案16】:

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

                    这可以通过这个函数来实现。
                    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

                    【讨论】:

                      【解决方案17】:

                      使用承诺:

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

                      【讨论】:

                        猜你喜欢
                        • 1970-01-01
                        • 2019-10-17
                        • 2017-05-19
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        相关资源
                        最近更新 更多