JavaScript: 注册事件处理程序的最佳位置

5

这个问题非常基础,我相信它一定是类似其他问题的重复提问,但是我仍然想要得到回答。

我的问题是: 最佳的地方去注册HTML元素的事件处理程序在哪里?

最简单的方法是直接在内联元素中注册事件处理程序:

<div id = "mybutton" onclick = "doSomething()">Click me</div>

但这与现代Web开发中逻辑和内容分离的压倒性趋势相矛盾。因此,在2012年,所有逻辑/行为都应该在纯Javascript代码中完成。这很好,并且会导致更易维护的代码。但是你仍然需要一些初始的钩子来将HTML元素与Javascript代码连接起来。

通常,我只需要做类似以下的事情:

<body onload = "registerAllEventHandlers()">

但是...这仍然是“作弊”,因为我们仍在使用内联JavaScript。但是我们还有哪些选项呢?我们不能在部分的

4个回答

2
你可以使用 window.onload:
<script type = "text/javascript">
  window.onload = registerAllEventHandlers;
</script>

如果您使用,则为:
$(registerAllEventHandlers);

使用 onload 是有效的,因为它会立即注册 onload 事件,但只有在 DOM 准备就绪时才会触发该事件。

-1:window.onload事件不等同于使用jQuery的ready事件:window.onload会在页面加载完成后触发,包括所有外部资源(图像、CSS等),而jQuery的ready事件将在HTML加载完成后但在外部资源之前触发。使用window.onload是一个坏主意,因为在许多情况下(许多图像、慢连接等),JavaScript事件需要很长时间才能被注册。 - georgebrock
@slebetman:你能详细解释一下为什么在图片(等等)加载之前附加JS事件处理程序是愚蠢的,并理解两种不同技术之间的区别吗?在一个旨在学习和分享信息的网站上,说“那很愚蠢”并没有什么建设性。 - georgebrock

0

我之前有类似的答案,但是那个是关于JavaScript的。不过思路还是一样的——在body标签结束前加载脚本。

利用抽象出来的库来处理window.onload和DOM ready事件。这样,你就可以在DOM准备好后立即加载脚本。


0

个人而言,我对在元素中添加onclick="doSomething();"没有任何问题。没有逻辑,只是一个函数调用。

所有的逻辑都应该在HEAD中定义的函数或单独的文件中。

告诉我,当你将href="somepage.html"甚至是href="somepage.html#someanchor"添加到A标签时有什么区别。


我很少只有一个需要添加行为的链接;通常是一组相似的链接。当这种行为发生变化或不再需要时,我发现更方便的方法是更改或删除单个.js文件,该文件定义了行为并将其附加到相关链接,而不是更改或删除许多链接上的许多onclick属性。 - georgebrock
@georgebrock 如果你想重新命名/重组你的HTML文件,你可以这么说 - 你仍然需要去每个A标签中改变href属性。无论如何,在你的情况下,不需要改变函数名,只需重写函数。如果onclick的行为正在改变,那么也许将函数名更改为其他名称是值得的。不过,你提出的观点很有道理。 - Matthew
一旦网站上线,更改href属性总是很麻烦的,因为好的URI不变(如果确实需要更改,应该使用301重定向到新位置)。但是我跑题了。既然您可以编写JavaScript以便一个地方进行单点更改并明确分离关注点,那为什么不这么做呢? - georgebrock
如果您更改的只是函数中的代码,则仍然可以使用内联onclick来实现单一更改点。至于为什么不分离事件处理程序:HTML的可读性 - 您无法仅通过查看HTML来确定按钮(例如)将执行什么操作,因为行为是在单独的文件中定义的。 - Matthew
也许我们只是来自不同的开发风格:我总是希望链接指向真实的URL,按钮提交真实的表单。如果我添加的链接或按钮没有JavaScript无法工作,那么我会使用JavaScript将其添加到页面中。 - georgebrock

0

在DOM准备就绪后,您应该立即注册事件处理程序。尽管在所有浏览器中检测这一点并不总是容易的,但除了IE 8(及更早版本)之外,现在大多数广泛使用的浏览器都支持DOMContentLoaded事件(感谢gengkev在评论中指出这一点)。

这基本上相当于在body的末尾调用您的registerAllEventHandlers函数,但它的优点是您不需要向HTML添加任何JavaScript。

它比使用window.onload要好得多,因为直到页面的所有资产(图像、CSS等)加载完毕才会执行。

如果您正在使用主要的JavaScript框架之一,那么即使在较旧版本的IE中,您也可以非常轻松地检测DOM是否已准备就绪。使用jQuery,您将使用ready事件

jQuery(document).ready(function () {
    // Your initialisation code here
});

或者简写为:

jQuery(function() { … });

使用 Prototype 您可以使用 dom:loaded 事件

document.observe("dom:loaded", function() {
    // Your initialisation code here
});

1
在几乎所有浏览器中,DOMContentLoaded都可以使用,但IE < 9除外。 - gengkev
我不知道现在这么广泛支持,我猜我太习惯于使用jQuery来帮助我了。谢谢@gengkev - georgebrock

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接