Wil*_*ham 642 javascript onclick addeventlistener
addEventListener
和之间有什么区别onclick
?
var h = document.getElementById("a");
h.onclick = dothing1;
h.addEventListener("click", dothing2);
Run Code Online (Sandbox Code Playgroud)
上面的代码一起存在于一个单独的.js文件中,它们都完美地工作.
Chr*_*ker 896
两者都是正确的,但它们本身都不是"最佳",开发人员可能选择使用这两种方法.
事件监听器(addEventListener和IE的attachEvent)
早期版本的Internet Explorer实现javascript与几乎所有其他浏览器不同.对于小于9的版本,您使用attachEvent
[ doc ]方法,如下所示:
element.attachEvent('onclick', function() { /* do stuff here*/ });
Run Code Online (Sandbox Code Playgroud)
在大多数其他浏览器(包括IE 9及更高版本)中,您使用addEventListener
[ doc ],如下所示:
element.addEventListener('click', function() { /* do stuff here*/ }, false);
Run Code Online (Sandbox Code Playgroud)
使用此方法(DOM Level 2事件),您可以将理论上无限数量的事件附加到任何单个元素.唯一的实际限制是客户端内存和其他性能问题,每个浏览器都有所不同.
上面的示例表示使用匿名函数[ doc ].您还可以使用函数引用[ doc ]或闭包[ doc ] 添加事件侦听器:
var myFunctionReference = function() { /* do stuff here*/ }
element.attachEvent('onclick', myFunctionReference);
element.addEventListener('click', myFunctionReference , false);
Run Code Online (Sandbox Code Playgroud)
另一个重要特性addEventListener
是最终参数,它控制侦听器对冒泡事件[ doc ]的反应.我在示例中传递了错误,这可能是95%的用例的标准.attachEvent
使用内联事件时没有等效参数.
内联事件(HTML onclick =""property和element.onclick)
在所有支持javascript的浏览器中,您可以将事件侦听器内联,即HTML代码中的内容.你可能已经看到了这个:
<a id="testing" href="#" onclick="alert('did stuff inline');">Click me</a>
Run Code Online (Sandbox Code Playgroud)
大多数有经验的开发人员都避开这种方法,但它确实完成了工作; 它简单直接.你可能不会在这里使用闭包或匿名函数(虽然处理程序本身是各种类型的匿名函数),并且你对范围的控制是有限的.
你提到的另一种方法:
element.onclick = function () { /*do stuff here */ };
Run Code Online (Sandbox Code Playgroud)
...相当于内联javascript,除了你有更多的范围控制(因为你正在编写脚本而不是HTML),并且可以使用匿名函数,函数引用和/或闭包.
内联事件的显着缺点是,与上述事件侦听器不同,您可能只分配了一个内联事件.内联事件存储为元素[ doc ] 的属性/属性,这意味着它可以被覆盖.
使用<a>
上面的HTML 示例:
var element = document.getElementById('testing');
element.onclick = function () { alert('did stuff #1'); };
element.onclick = function () { alert('did stuff #2'); };
Run Code Online (Sandbox Code Playgroud)
...当你点击元素时,你只会看到"Did stuff#2" - 你onclick
用第二个值覆盖了第一个赋值的属性,并且你也覆盖了原始的内联HTML onclick
属性.在这里查看:http://jsfiddle.net/jpgah/.
一般来说,不要使用内联事件.可能存在特定的用例,但如果您不是100%确定您拥有该用例,那么您不会也不应该使用内联事件.
现代Javascript(Angular之类)
由于这个答案最初发布,像Angular这样的javascript框架变得更加流行.你会在Angular模板中看到这样的代码:
<button (click)="doSomething()">Do Something</button>
Run Code Online (Sandbox Code Playgroud)
这看起来像一个内联事件,但事实并非如此.这种类型的模板将被转换为更复杂的代码,后者在幕后使用事件监听器.我在这里所写的关于事件的所有内容仍然适用,但是至少有一层将你从细节中删除.您应该了解这些细节,但如果您的现代JS框架最佳实践涉及在模板中编写此类代码,请不要觉得您正在使用内联事件 - 您不是.
哪个最好?
问题在于浏览器的兼容性和必要性.您当前是否需要将多个事件附加到元素?你将来会吗?赔率是,你会的.attachEvent和addEventListener是必要的.如果没有,内联事件可能看起来像他们会做的那样,但是你为未来做好准备,尽管看起来似乎不太可能,至少可以预测.有可能你必须转移到基于JS的事件监听器,所以你也可以从那里开始.不要使用内联事件.
jQuery和其他javascript框架在通用模型中封装了DOM 2级事件的不同浏览器实现,因此您可以编写跨浏览器兼容的代码,而无需担心IE作为反叛者的历史.与jQuery相同的代码,所有跨浏览器并准备好摇滚:
$(element).on('click', function () { /* do stuff */ });
Run Code Online (Sandbox Code Playgroud)
但是,不要为了这一件事而耗尽并获得一个框架.您可以轻松地滚动自己的小实用程序来处理旧版浏览器:
function addEvent(element, evnt, funct){
if (element.attachEvent)
return element.attachEvent('on'+evnt, funct);
else
return element.addEventListener(evnt, funct, false);
}
// example
addEvent(
document.getElementById('myElement'),
'click',
function () { alert('hi!'); }
);
Run Code Online (Sandbox Code Playgroud)
试试吧:http://jsfiddle.net/bmArj/
考虑到所有这些因素,除非您正在查看的脚本以其他方式考虑浏览器差异(在您的问题中未显示的代码中),addEventListener
否则使用的部分将无法在小于9的IE版本中使用.
文件和相关阅读
lon*_*day 170
如果您有另外两个功能,您可以看到差异:
var h = document.getElementById('a');
h.onclick = doThing_1;
h.onclick = doThing_2;
h.addEventListener('click', doThing_3);
h.addEventListener('click', doThing_4);
Run Code Online (Sandbox Code Playgroud)
功能2,3和4工作,但1不工作.这是因为addEventListener
不会覆盖现有的事件处理程序,而是onclick
覆盖任何现有的onclick = fn
事件处理程序.
当然,另一个显着的区别是,它onclick
始终有效,而addEventListener
在版本9之前的Internet Explorer中不起作用.您可以在IE <9中使用类似的attachEvent
(语法略有不同).
Mic*_*ski 59
在这个答案中,我将描述定义DOM事件处理程序的三种方法.
element.addEventListener()
代码示例:
const element = document.querySelector('a');
element.addEventListener('click', event => event.preventDefault(), true);
Run Code Online (Sandbox Code Playgroud)
<a href="//google.com">Try clicking this link.</a>
Run Code Online (Sandbox Code Playgroud)
element.addEventListener()
有多重优势:
element.removeEventListener()
.useCapture
参数,表示您是否想要在捕获或冒泡阶段处理事件.请参阅:无法理解addEventListener中的useCapture属性..onevent
DOM元素的属性,许多没有经验的JavaScript程序员认为事件名称是例如onclick
或onload
.on
是不是事件名称的一部分.正确的事件名称是click
和load
,以及事件名称的传递方式.addEventListener()
.element.onevent = function() {}
(例如onclick
,onload
)代码示例:
const element = document.querySelector('a');
element.onclick = event => event.preventDefault();
Run Code Online (Sandbox Code Playgroud)
<a href="//google.com">Try clicking this link.</a>
Run Code Online (Sandbox Code Playgroud)
这是一种在DOM 0中注册事件处理程序的方法.现在不鼓励这样做,因为它:
onevent
属性还原回其初始状态(即null
).window.onload
,例如:window.onload = "test";
,则不会抛出任何错误.你的代码不起作用,很难找到原因..addEventListener()
然而,会抛出错误(至少在Firefox中):TypeError:EventTarget.addEventListener的参数2不是对象.onevent
HTML属性)代码示例:
<a href="//google.com" onclick="event.preventDefault();">Try clicking this link.</a>
Run Code Online (Sandbox Code Playgroud)
与此类似element.onevent
,现在不鼓励了.除了问题element.onevent
,它:
Content-Security-Policy
HTTP标头来阻止内联脚本,并且只允许来自可信域的外部脚本.请参阅内容安全策略如何工作?EventTarget.addEventListener()
文档(MDN)EventTarget.removeEventListener()
文档(MDN)Mag*_*nar 22
虽然onclick
适用于所有浏览器,addEventListener
但在旧版本的Internet Explorer中无法使用attachEvent
.
缺点onclick
是只能有一个事件处理程序,而其他两个将触发所有已注册的回调.
jAn*_*ndy 12
据我所知,DOM"加载"事件仍然只起作用非常有限.这意味着它只会火了window object
,images
和<script>
例如元素.直接onload
分配也是如此.这两者之间没有技术差异.可能.onload =
有更好的跨浏览器可用性.
但是,您无法将load event
a <div>
或<span>
元素或其他内容分配给.
一个元素对于每种事件类型只能附加一个事件处理程序,但可以有多个事件侦听器。
那么,它的实际效果如何呢?
仅运行分配的最后一个事件处理程序:
const button = document.querySelector(".btn")
button.onclick = () => {
console.log("Hello World");
};
button.onclick = () => {
console.log("How are you?");
};
button.click() // "How are you?"
Run Code Online (Sandbox Code Playgroud)
所有事件监听器都会被触发:
const button = document.querySelector(".btn")
button.addEventListener("click", event => {
console.log("Hello World");
})
button.addEventListener("click", event => {
console.log("How are you?");
})
button.click()
// "Hello World"
// "How are you?"
Run Code Online (Sandbox Code Playgroud)
IE 注意:attachEvent
不再支持。从 IE 11 开始,使用addEventListener
: docs。
addEventListener
可以添加多个事件,而onclick
不能这样做。onclick
可以作为HTML
属性添加,而addEventListener
只能在<script>
元素内添加。addEventListener
可以采用第三个参数来停止事件传播。两者都可以用来处理事件。但是,它addEventListener
应该是首选,因为它可以做所有事情onclick
以及更多。不要将内联onclick
用作HTML属性,因为这会将javascript和HTML混合在一起,这是一种不好的做法。它使代码的可维护性降低。
有一个细节没有注意到尚:现代桌面浏览器考虑不同的按键操作是“点击”了AddEventListener('click'
,并onclick
在默认情况下。
onclick
并AddEventListener
单击火左边和中间点击。onclick
触发仅在左侧点击,但AddEventListener
点击左,中火和右点击。此外,当涉及滚动光标时,跨浏览器的中键行为非常不一致:
还值得注意的是,任何可用键盘选择的 HTML 元素的“单击”事件,例如input
也会在空格上触发或在元素被选择时输入。
\n\nelement.onclick = function() { /* 做一些事情 */ }
\nelement.addEventListener(\'click\', function(){ /* 执行操作 */ },false);
\n
他们显然做了同样的事情:监听点击事件并执行回调函数。然而,它们\xe2\x80\x99并不等效。如果您需要在两者之间进行选择,这可以帮助您找出最适合您的一个。
\n主要区别在于onclick 只是一个属性,并且像所有对象属性一样,如果多次写入,它将被覆盖。使用addEventListener()代替,我们可以简单地绑定一个事件处理程序到元素,并且每次需要时都可以调用它,而不必担心任何属性被覆盖。\n示例如下所示,
\n尝试一下: https: //jsfiddle.net/fjets5z4/5/
\n首先,我很想继续使用 onclick,因为它 \xe2\x80\x99 更短,看起来更简单 \xe2\x80\xa6 事实上它是。但我不建议再使用它。它\xe2\x80\x99s 就像使用内联 JavaScript 一样。现在非常不鼓励使用像 \xe2\x80\x93 这样的东西,\xe2\x80\x99s 内联 JavaScript \xe2\x80\x93 (内联 CSS 也不鼓励,但是 \xe2\x80\x99s 是另一个主题)。
\n然而,addEventListener() 函数尽管\xe2\x80\x99 是标准的,但在旧浏览器(版本 9 以下的 Internet Explorer)中不起作用,这是另一个很大的区别。如果你需要支持这些古老的浏览器,你应该遵循onclick方式。但您也可以使用 jQuery(或其替代方案之一):它基本上简化了您的工作并减少了浏览器之间的差异,因此可以节省您大量时间。
\nvar clickEvent = document.getElementByID("onclick-eg");\nvar EventListener = document.getElementByID("addEventListener-eg");\n\nclickEvent.onclick = function(){\n window.alert("1 is not called")\n}\nclickEvent.onclick = function(){\n window.alert("1 is not called, 2 is called")\n}\n\nEventListener.addEventListener("click",function(){\n window.alert("1 is called")\n})\nEventListener.addEventListener("click",function(){\n window.alert("2 is also called")\n})\n
Run Code Online (Sandbox Code Playgroud)\n
小智 5
您还应该考虑 EventDelegate!出于这个原因,我更喜欢 addEventListener 并且最重要的是仔细且有意识地使用它!
事实:
想象一个简单的例子:一个简单的按钮位于 div 内部的主体中...如果您单击按钮,事件无论如何都会流入 BUTTON,然后再次流出,如下所示:
窗口文档 div 按钮 div 文档窗口
在浏览器后台(比如说 JS 引擎的软件外围),如果浏览器检查目标位置上的每次点击,它只能对点击做出反应。
为了确保触发途中每个可能的事件侦听器,它必须将“单击事件信号”从文档级别一直发送到元素......然后再次返回。然后可以通过附加 EventListeners 使用此行为,例如:
document.getElementById("exampleID").addEventListener("click",(event) => {doThis}, true/false);
Run Code Online (Sandbox Code Playgroud)
请注意,作为 addEventListener 方法的最后一个参数的 true/false 控制事件何时被识别的行为 - 当滴入或冒泡时。
TRUE 表示事件在滴入时被识别 FALSE 表示事件在冒泡时被识别
使用上述处理方法来实现以下两个有用的概念也变得更加直观:
event.stopPropagation()
您还可以在函数内使用(示例参考“doThis”)来防止当前事件在捕获和冒泡阶段进一步传播。然而,它并不能阻止任何默认行为的发生;例如,仍然会处理链接的点击。event.preventDefault()
在函数内使用(示例参考“doThis”)。例如,您可以告诉浏览器,如果事件没有得到显式处理,则不应像通常那样采取其默认操作。另外请注意此处再次参考:addEventListener 方法的最后一个参数(true/false)还控制“.stopPropagation()”的最终效果在哪个阶段(滴入 TRUE 或冒泡出 FALSE)生效。所以。 ..如果您将带有 TRUE 标志的 EventListener 应用于元素,并将其与 .stopPropagation() 方法结合使用,该事件甚至不会到达该元素的潜在内部子元素
总结一下:如果您在 HTML 中使用 onClick 变体...对我来说有 2 个缺点:
关于事件委托,实际上可以归结为这一点。如果其他一些 JavaScript 代码需要响应单击事件,则使用 addEventListener 可确保双方都可以响应它。如果你们都尝试使用 onclick,那么一个会踩到另一个。如果您想要对同一元素进行 onclick,则双方都无法响应。
Furthermore, you want to keep your behavior as separate as you can from the HTML in case you need to change it later. It would suck to have 50 HTML files to update instead of one JavaScript file.
(归功于 Greg Burghardt,addEventListener 与 onclick 关于事件委托的比较)
归档时间: |
|
查看次数: |
496217 次 |
最近记录: |