我开发 Joomla 网站/组件/模块和插件,并且我经常需要能够使用在页面加载时触发事件的 JavaScript。大多数情况下,这是使用该window.onload
功能完成的。
我的问题是:
- 这是在页面加载时触发 JavaScript 事件的最佳方式还是有更好/更新的方式?
- 如果这是在页面加载时触发事件的唯一方法,那么确保多个事件可以由不同的脚本运行的最佳方法是什么?
我开发 Joomla 网站/组件/模块和插件,并且我经常需要能够使用在页面加载时触发事件的 JavaScript。大多数情况下,这是使用该window.onload
功能完成的。
我的问题是:
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)事件,它们可以应用于文档对象以了解何时可以操作文档(无需等待所有图像/样式表等..要加载)。
有很多跨浏览器支持的“hacky”实现,所以我强烈建议使用这个功能的框架。
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);
}
现代 javascript 框架引入了“文档就绪”事件的概念。这是一个在文档准备好对其执行 DOM 操作时触发的事件。“onload”事件仅在页面上的所有内容都加载后才会触发。
除了“文档就绪”事件之外,框架还提供了一种方法,可以将多个 Javascript 代码和函数排队,以便在事件触发时运行。
所以,如果你反对框架,最好的办法就是实现你自己的 document.onload 队列。
如果您不反对框架,那么您将需要研究jQuery 和 document.ready、Prototype 和 dom:loaded、Dojo 和 addOnLoad或 Google 的 [your framework] 和“document ready”。
如果您尚未选择框架但有兴趣,那么 jQuery 是一个不错的起点。它不会改变 Javascript 的任何核心功能,并且通常不会妨碍您,让您随心所欲地做事。
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
就个人而言,我更喜欢这种方法。它不仅允许您拥有多个onload
功能,而且如果某个脚本在您使用它之前已经定义了它,那么这个方法就可以很好地处理它......剩下的唯一问题是如果一个页面加载了几个不使用的脚本window.addLoad()
函数;但这是他们的问题:)。
PS 如果您以后想“链接”更多功能,它也很棒。
这是肮脏但较短的方式:P
function load(){
*code*
}
window[ addEventListener ? 'addEventListener' : 'attachEvent' ]
( addEventListener ? 'load' : 'onload', function(){} )
由于我总是在文档底部包含 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();
});