Javascript onclick="" vs 事件处理程序
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6941483/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
onclick="" vs event handler
提问by Johan
If I want a function to be executed, I prefer doing inline js:
如果我想执行一个函数,我更喜欢使用内联 js:
<p id="element" onclick="doSomething();">Click me</p>
because it is easier to debug.
因为更容易调试。
However, I hear people saying not to use inline js, and do:
但是,我听到有人说不要使用内联 js,而是这样做:
document.getElementById('element').onclick = doSomething;
Why is the js event listener recommended?
为什么推荐js事件监听器?
采纳答案by LeeR
Basically it has to do with the whole keep everything separate I believe. So keep HTML/CSS/JS all separate. It makes your HTML tidier and, I think, easier to navigate without.
基本上它与整体保持一切分开我相信。所以保持 HTML/CSS/JS 全部分开。它使您的 HTML 更整洁,而且我认为没有它更容易导航。
Then when/if you need to make large changes, you have ample space with having to shift the inline JS to an external file anyway OR if you want to apply the same function to more than one button, then it's less code. And less code is a happier place
然后,当/如果您需要进行大量更改时,您有足够的空间,无论如何必须将内联 JS 转移到外部文件,或者如果您想将相同的功能应用于多个按钮,那么代码更少。更少的代码是一个更快乐的地方
If you have your JS files properly, and thoroughly documented then navigating them by an outside person is made eaiser
如果您的 JS 文件正确且完整记录,那么由外部人员导航它们会更容易
回答by Felix Kling
One big argument against inline event handlers, and the argument that is addressed by the other answers here is the separation of presentation and logic.
反对内联事件处理程序的一大论点,以及这里其他答案所解决的论点是表示和逻辑的分离。
However, there is actually a bigger problem IMO: The somehow elusive way how inline event handlers are evaluated.
然而,IMO 实际上有一个更大的问题:内联事件处理程序的评估方式以某种方式难以捉摸。
As you may know, the content of the on*
attributes will be used as bodyof the event handler function. But what characteristics does this function have?
您可能知道,on*
属性的内容将用作事件处理函数的主体。但是这个函数有什么特点呢?
One of the surprising ones is that properties of some ancestor elementsand of the element itselfare in the scopeof the inline event handler.
令人惊讶的一个是一些祖先元素的属性和元素本身的属性在内联事件处理程序的范围内。
<form>
<input name="foo" />
<button type="button" onclick="console.log(foo); console.log(window.foo);">
Click me
</button>
<div onclick="console.log(foo);">Click me as well!</div>
</form>
Clicking the button
logs
单击button
日志
<input name="foo"></input>
undefined
in the console. The fact that window.foo
is undefined
tells you that there is no global variable foo
. So where does the variable foo
come from? Why does console.log(foo)
log the input element and not throw a reference error?
Because the properties of the form
element are in the scope of the event handler and the form
element has a property for each named form control element it contains. You can easily test this with console.log(document.querySelector('form').foo)
.
在控制台中。事实window.foo
是undefined
告诉你没有全局变量foo
。那么变量foo
从何而来?为什么console.log(foo)
记录输入元素而不抛出引用错误?
因为form
元素的属性在事件处理程序的范围内,并且form
元素对于它包含的每个命名表单控件元素都有一个属性。您可以使用console.log(document.querySelector('form').foo)
.
Now, clicking the div
element actually throws a reference error:
现在,单击该div
元素实际上会引发引用错误:
ReferenceError: foo is not defined
ReferenceError: foo is not defined
So apparently the form
element is only in scope of form control elements, not any descendant. How confusing is that?
因此显然该form
元素仅在表单控件元素的范围内,而不是任何后代。这有多混乱?
Similarly, the properties of the document
object are also in the scope of inline event handlers, which can lead to some surprising bugs(did you know that document
has a property plugins
?).
同样,对象的属性document
也在内联事件处理程序的范围内,这可能会导致一些令人惊讶的错误(你知道它document
有一个属性plugins
吗?)。
How exactly inline event handlers are evaluated is formalized in the HTML5 spec. Have a loop at step 10 in particular where he scope chain creation is described.
HTML5 规范中规定了如何准确评估内联事件处理程序。在第 10 步有一个循环,特别是在描述范围链创建的地方。
Conclusion:
结论:
Because of this implicitconnection between elements and inline event handlers, bugs can be really hard to track. It's of course fine to use inline event handlers if you just want to test something. But using them in production code comes with a higher maintenance cost.
由于元素和内联事件处理程序之间的这种 隐式联系,错误可能很难跟踪。如果你只是想测试一些东西,使用内联事件处理程序当然很好。但是在生产代码中使用它们会带来更高的维护成本。
The articles at quirksmode.orgexplain the different ways of binding event handlers and their (dis)advantages very well.
quirksmode.org 上的文章很好地解释了绑定事件处理程序的不同方式及其(缺点)优点。
回答by brezanac
There are a lot of reasons to avoid inline JavaScript and one of the perhaps most important is code maintainability.
避免内联 JavaScript 的原因有很多,其中最重要的原因之一可能是代码的可维护性。
A quick example (I am using jQuery simply for demonstration purposes).
一个简单的例子(我使用 jQuery 只是为了演示目的)。
<p class="element" onclick="doSomething();">Click me</p>
<p class="element" onclick="doSomething();">Click me</p>
<p class="element" onclick="doSomething();">Click me</p>
<p class="element" onclick="doSomething();">Click me</p>
<p class="element" onclick="doSomething();">Click me</p>
<p class="element" onclick="doSomething();">Click me</p>
What if suddenly you get a request to change all your paragraphs to execute another function? In your example you would have to change everything manually in your HTML code. However if you choose to separate HTML from JavaScript you could simply do it like this.
如果您突然收到更改所有段落以执行另一个功能的请求怎么办?在您的示例中,您必须手动更改 HTML 代码中的所有内容。但是,如果您选择将 HTML 与 JavaScript 分开,您可以简单地这样做。
<p class="element">Click me</p>
<p class="element">Click me</p>
<p class="element">Click me</p>
<p class="element">Click me</p>
<p class="element">Click me</p>
<p class="element">Click me</p>
$('.element').bind('click', doSomethingElse);
The HTML code is also cleaner which allows the designers to focus exclusively on design without fear that they might actually break something while working on a project which also involves other people.
HTML 代码也更清晰,这使设计人员可以专注于设计,而不必担心他们在处理涉及其他人的项目时可能会实际破坏某些内容。
EDIT:Providing example for my comment bellow.
编辑:为我下面的评论提供示例。
Project = {
// All the variables/constants/objects that need to be globally accessible inside the Project object.
init : function(){
// Main entry point...
this.MainMenu.init();
// Rest of the code which should execute the moment Project is initiated.
}
}
Project.MainMenu = {
// All the variables/constants/objects that need to be accessible only to MainMenu.
init : function(){ // Is run immediatelly by Project.init()
// Event handlers relevant to the main menu are bound here
// Rest of the initialization code
}
}
Project.SlideShow = {
// All the variables/constants/objects that need to be accessible only to SlideShow.
init : function(){ // Is run only on pages that really require it.
// Event handlers for the slideshow.
}
}
回答by ming_codes
Despite what other people may think, I think there are redeeming value to inlining listeners in markup. Specifically, it gives you a lot more freedom to modifying the DOM nodes. If you're adding listeners though JavaScript, the listeners are lost when you replace the innerHTML of any parent nodes. If you're inlining the listeners in markup, you can clone the node, make modifications to it, then replace the original node with the node you just cloned and modified.
尽管其他人可能会这么想,但我认为在标记中内联侦听器是有价值的。具体来说,它为您提供了更多修改 DOM 节点的自由。如果您通过 JavaScript 添加侦听器,当您替换任何父节点的 innerHTML 时,侦听器将丢失。如果您在标记中内联侦听器,您可以克隆节点,对其进行修改,然后用您刚刚克隆和修改的节点替换原始节点。
Perhaps it's better to describe it in a specific use case. I want to make changes to multiple part of the document without triggering reflow multiple times. So in this case, I can clone the node, make any change to it (no reflow since its detached), then replace the previous node with the modified one (triggering one reflow). With inlined listeners, this prevents any listeners from getting lost during the replacement.
也许最好在特定用例中描述它。我想在不多次触发回流的情况下对文档的多个部分进行更改。所以在这种情况下,我可以克隆节点,对其进行任何更改(因为它分离后没有回流),然后用修改后的节点替换前一个节点(触发一次回流)。使用内联侦听器,这可以防止任何侦听器在替换过程中丢失。
回答by ProxyTech
I see some saying there needs to be a separation of concerns regarding Presentation and Business Logic.
我看到有人说需要将有关表示和业务逻辑的关注点分开。
OP in his example does indeed show this separation! There is no logic in the inline event handler, but merely a function reference/call that will get executed on the "click" event... the logic itself can be separately maintained elsewhere.
OP 在他的例子中确实显示了这种分离!内联事件处理程序中没有逻辑,而只是一个将在“单击”事件上执行的函数引用/调用……逻辑本身可以在其他地方单独维护。
I personally prefer this approach due to logical flow discoverability. If I have never seen an application before... the first place I'm going to begin my code traversal is in the DOM, and right there it will be clear which event handlers are in play and which functions are providing the logic to the handlers. With using, say a "JQuery.On" eventing approach, by just glancing through the html you would have no idea which handlers are actually wired up and providing functionality.
由于逻辑流的可发现性,我个人更喜欢这种方法。如果我以前从未见过应用程序......我要开始我的代码遍历的第一个地方是在 DOM 中,在那里很清楚哪些事件处理程序在起作用,哪些函数正在为处理程序。使用,比如说“JQuery.On”事件方法,通过浏览 html,您将不知道哪些处理程序实际上已连接并提供功能。
Inline event handlers that simply provide pointers to functions is simply wiring up the events and not leaking logic into presentation.
简单地提供函数指针的内联事件处理程序只是简单地连接事件而不是将逻辑泄漏到表示中。
回答by Shekhar Reddy
Apart from the coding standards perspective
除了编码标准之外
Using Attributes:
使用属性:
<p id="element" onclick="doSomething();">Click me</p>
<p id="element" onclick="doSomething();">Click me</p>
if you add the same attribute again (see below) -the latest one is considered.
如果您再次添加相同的属性(见下文) - 将考虑最新的属性。
<p id="element" onclick="doSomethingMore();">Click me</p>
<p id="element" onclick="doSomethingMore();">Click me</p>
Using Event Handler:
使用事件处理程序:
document.getElementById('element').onclick = doSomething;
document.getElementById('element').onclick = doSomething;
and lets say you added the below line
假设您添加了以下行
document.getElementById('element').onclick = doSomethingMore;
Both the handlers are invoked.
document.getElementById('element').onclick = doSomethingMore;
两个处理程序都被调用。
回答by wezzy
I'm not aware of and advantage of using inline handler vs attach the handler later. In my experience I prefer to use the inline method when I have to deal with dynamic elements, for example if I want to add an handler to each image and the number of images changes according to other data (ex images in db). In this case using inline allow me to add an handler to each image, otherwise i have to recalculate the number of images in the javascript file to attach and handler to each image.
我不知道使用内联处理程序与稍后附加处理程序的优势。根据我的经验,当我必须处理动态元素时,我更喜欢使用内联方法,例如,如果我想为每个图像添加一个处理程序,并且图像数量会根据其他数据(例如 db 中的图像)发生变化。在这种情况下,使用内联允许我为每个图像添加一个处理程序,否则我必须重新计算 javascript 文件中要附加和处理每个图像的图像数量。
Of course, when you can use libraries like jQuery where you can easily get the list of elements inline aren't useful
当然,当您可以使用像 jQuery 这样可以轻松获取内联元素列表的库时,这些库是没有用的
回答by Loktar
You could say the same about CSS and including inline styles. It would be easy to not have to wade through a css file to find the current class/id, or parent/child elements your working with.
您可以对 CSS 和包括内联样式说同样的话。不必费力地通过 css 文件来查找当前的类/ID 或您使用的父/子元素会很容易。
Is it really better to bind a click to say 10 different items inline? Or just one event handler targeting a class? Even if you don't need 10 click handlers its always a better idea to set your code up for maintainability, and upgrades down the road.
绑定一个点击来内联说 10 个不同的项目真的更好吗?或者只是一个针对一个类的事件处理程序?即使您不需要 10 个点击处理程序,将代码设置为可维护性并在未来进行升级总是一个更好的主意。