40

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

我的问题是:

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

7 回答 7

46

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

我想说更好/更新的方法是使用框架,或者只是使用本机addEventListenerattachEvent(对于 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)事件,它们可以应用于文档对象以了解何时可以操作文档(无需等待所有图像/样式表等..要加载)。

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

于 2009-02-17T23:15:43.593 回答
13

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);
}
于 2012-08-21T14:24:05.510 回答
10

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

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

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

如果您不反对框架,那么您将需要研究jQuery 和 document.readyPrototype 和 dom:loadedDojo 和 addOnLoad或 Google 的 [your framework] 和“document ready”。

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

于 2009-02-17T23:44:25.037 回答
2

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

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

更多关于 MooTools 的信息可以在这里找到。Joomla 1.5 目前附带 MT1.1,而 Joomla 1.6 alpha 将包括 MT1.2

于 2009-06-24T19:17:08.090 回答
1

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

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

于 2009-02-18T03:26:57.687 回答
1

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

function load(){
   *code*
}

window[ addEventListener ? 'addEventListener' : 'attachEvent' ]
( addEventListener ? 'load' : 'onload', function(){} )
于 2012-09-14T09:34:11.657 回答
0

由于我总是在文档底部包含 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();
});
于 2015-10-23T09:16:28.630 回答