【问题标题】:Best practice for using window.onload使用 window.onload 的最佳实践
【发布时间】:2010-10-08 05:34:33
【问题描述】:

我开发 Joomla 网站/组件/模块和插件,我经常需要能够使用 JavaScript 来在页面加载时触发事件。大多数情况下,这是使用window.onload 函数完成的。

我的问题是:

  1. 这是在页面加载时触发 JavaScript 事件的最佳方式还是有更好/更新的方式?
  2. 如果这是在页面加载时触发事件的唯一方法,那么确保不同脚本可以运行多个事件的最佳方法是什么?

【问题讨论】:

    标签: javascript joomla joomla1.5 onload


    【解决方案1】:

    由于我总是在文档底部包含 jQuery/bootstrap JS 文件,并且无法通过文档访问 $,因此我开发了一个小型“init”插件,它是我在最顶部包含的唯一一个 JS 脚本我的页面:

    window.init = new function() {
        var list = [];
    
        this.push = function(callback) {
            if (typeof window.jQuery !== "undefined") {
                callback();
            } else {
                list.push(callback);
            }
        };
    
        this.run = function() {
    
            if (typeof window.jQuery !== "undefined") {
                for(var i in list) {
                    try {
                        list[i]();
                    } catch (ex) {
                        console.error(ex);
                    }
                }
                list = [];
            }
        };
    
        if (window.addEventListener) {
            window.addEventListener("load", this.run, false);
        } else if (window.attachEvent) {
            window.attachEvent("onload", this.run);
        } else {
            if (window.onload && window.onload !== this.run) {
                this.push(window.onload);
            }
            window.onload = this.run;
        }
    };
    

    使用它,我可以在页面上定义任何匿名加载器,在 jQuery 和引导程序包含之前,并确保它会在 jQuery 存在时触发:

    init.push(function() {
    
        $('[name="date"]').datepicker({
            endDate: '0d',
            format: 'yyyy-mm-dd',
            autoclose: true
        }).on('hide', function() {
            // $.ajax
        });
    
        $('[name="keyword_id"]').select2();
    });
    

    【讨论】:

      【解决方案2】:

      现代 javascript 框架引入了“文档就绪”事件的概念。这是一个在文档准备好对其执行 DOM 操作时触发的事件。 “onload”事件仅在页面上的所有内容都加载后才会触发。

      除了“文档就绪”事件之外,框架还提供了一种方法,可以将多个 Javascript 代码和函数排队,以便在事件触发时运行。

      所以,如果你反对框架,最好的办法是实现你自己的 document.onload 队列。

      如果您不反对框架,那么您需要查看jQuery and document.ready、Prototype and dom:loaded、Dojo and addOnLoad 或 Google 以获取 [您的框架] 和“文档就绪”。

      如果您尚未选择框架但有兴趣,jQuery 是一个不错的起点。它不会改变 Javascript 的任何核心功能,并且通常不会妨碍您,让您随心所欲地做事。

      【讨论】:

      • 对 onload 队列实现有什么好的参考,或者更多解释文档就绪和 onload 事件之间的区别?
      • 我不想卷入内容争议,但像 jQuery 这样的库真的不是框架。见stackoverflow.com/q/7062775/1348195
      • 我可以看到这两个方面,但 Web 开发人员使用 jQuery 的方式更像是一个框架,无论项目如何自我描述。这对我来说似乎是一个意见、观点和作者身份的问题——尤其是因为我指的是更广泛的 javascript 世界和 document.ready 技术。没有恶意或争论。
      • 当然,Stack Overflow 可以让你写下任何你想要的答案,除了答案听起来不错。但是,事情已经很好地定义了,答案的一部分在客观上是错误的。事实上,正如答案所描述的那样,“它不会改变 Javascript 的任何核心功能,并且通常不会妨碍您,让您随心所欲地做事”准确地说为什么它是一个库而不是一个框架。 jQuery 和类似的 DOM 操作库不执行控制反转,它们只是提供用于编写​​代码的实用程序。没有好莱坞的方法:)
      【解决方案3】:

      window.onload = function(){}; 有效,但您可能已经注意到,它只允许您指定 1 个侦听器。

      我想说更好/更新的方法是使用框架,或者只是使用本机 addEventListener 和 attachEvent(对于 IE)方法的简单实现,它允许您删除事件的监听器。

      这是一个跨浏览器的实现:

      // Cross-browser implementation of element.addEventListener()
      function listen(evnt, elem, func) {
          if (elem.addEventListener)  // W3C DOM
              elem.addEventListener(evnt,func,false);
          else if (elem.attachEvent) { // IE DOM
               var r = elem.attachEvent("on"+evnt, func);
               return r;
          }
          else window.alert('I\'m sorry Dave, I\'m afraid I can\'t do that.');
      }
      
      // Use: listen("event name", elem, func);
      

      对于 window.onload 案例使用:listen("load", window, function() { });


      编辑我想通过添加其他人指出的宝贵信息来扩展我的答案。

      这是关于 DOMContentLoaded(Mozilla、Opera 和 webkit nightlies 目前支持此功能)和 onreadystatechange(适用于 IE)事件 em> 可以应用于 document 对象以了解何时可以操作文档(无需等待所有图像/样式表等被加载)。

      对于跨浏览器的支持有很多“hacky”实现,所以我强烈建议使用这个功能的框架。

      【讨论】:

      • 我要大力推广jQuery的.ready()功能:api.jquery.com/ready
      • +1 for "1 listener only",这正是我现在需要的提示!
      • 我喜欢这条警告信息:D
      【解决方案4】:

      这是肮脏但更短的方式:P

      function load(){
         *code*
      }
      
      window[ addEventListener ? 'addEventListener' : 'attachEvent' ]
      ( addEventListener ? 'load' : 'onload', function(){} )
      

      【讨论】:

        【解决方案5】:

        window.onload 事件在多次创建时被覆盖。要附加函数,请使用 window.addEventListener(W3C 标准)或 window.attachEvent(对于 IE)。使用以下有效的代码。

        if (window.addEventListener) // W3C standard
        {
          window.addEventListener('load', myFunction, false); // NB **not** 'onload'
        } 
        else if (window.attachEvent) // Microsoft
        {
          window.attachEvent('onload', myFunction);
        }
        

        【讨论】:

          【解决方案6】:

          Joomla 附带 MooTools,因此您会发现将 MooTools 库用于您的附加代码是最容易的。 MooTools 附带了一个名为 domready 的自定义事件,该事件在页面加载和文档树被解析时触发。

          window.addEvent( domready, function() { code to execute on load here } );
          

          有关 MooTools 的更多信息,请访问here。 Joomla 1.5 目前附带 MT1.1,而 Joomla 1.6 alpha 将包括 MT1.2

          【讨论】:

          • 这个答案在当时是有效的,但在较新版本的 Joomla JQuery 中使用。
          【解决方案7】:

          就个人而言,我更喜欢this method。它不仅允许您拥有多个 onload 函数,而且如果某些脚本在之前定义了它,那么此方法足以处理它......剩下的唯一问题是如果一个页面加载了几个不使用window.addLoad()函数的脚本;但这是他们的问题:)。

          附:如果您以后想“链接”更多功能,它也很棒。

          【讨论】:

            猜你喜欢
            • 2012-12-31
            • 1970-01-01
            • 2017-11-29
            • 2012-04-11
            • 2010-12-04
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多