addEventListener与onclick

2020/09/21 17:31 · javascript ·  · 0评论

addEventListener之间有什么区别onclick

var h = document.getElementById("a");
h.onclick = dothing1;
h.addEventListener("click", dothing2);

上面的代码一起驻留在单独的.js文件中,并且它们都可以正常工作。

两种方法都是正确的,但是它们本身都不是“最佳”的,并且开发人员选择使用这两种方法可能是有原因的。

事件监听器(addEventListener和IE的attachEvent)

早期版本的Internet Explorer与几乎所有其他浏览器相比,实现javascript的方式有所不同。对于小于9的版本,可以使用attachEvent[ doc ]方法,如下所示:

element.attachEvent('onclick', function() { /* do stuff here*/ });

在大多数其他浏览器(包括IE 9及更高版本)中,您可以使用addEventListener[ doc ],如下所示:

element.addEventListener('click', function() { /* do stuff here*/ }, false);

使用这种方法(DOM 2级事件),您可以将理论上不受限制的事件数量附加到任何单个元素。唯一实际的限制是客户端内存和其他性能问题,这对于每个浏览器都是不同的。

上面的示例表示使用匿名函数[ doc ]。您还可以使用函数reference [ doc ]或闭包[ doc ] 添加事件侦听器

var myFunctionReference = function() { /* do stuff here*/ }

element.attachEvent('onclick', myFunctionReference);
element.addEventListener('click', myFunctionReference , false);

的另一个重要功能addEventListener是final参数,该参数控制侦听器对冒泡事件的反应[ doc ]。我在示例中传递了错误,这可能是95%用例的标准。attachEvent或使用内联事件时,没有等效参数

内联事件(HTML onclick =“”属性和element.onclick)

在所有支持javascript的浏览器中,您都可以内嵌事件监听器,这意味着HTML代码中的内容。您可能已经看到了:

<a id="testing" href="#" onclick="alert('did stuff inline');">Click me</a>

大多数有经验的开发人员都避免使用这种方法,但是它确实可以完成工作。简单而直接。您不能在此处使用闭包或匿名函数(尽管处理程序本身是某种匿名函数),并且您对范围的控制受到限制。

您提到的另一种方法:

element.onclick = function () { /*do stuff here */ };

除了可以更好地控制范围(因为您正在编写脚本而不是HTML),并且可以使用匿名函数,函数引用和/或闭包之外,...等效于内联javascript。

内联事件的主要缺点是,与上述事件侦听器不同,您只能分配一个内联事件。内联事件存储为element [ doc ] 的属性/属性,意味着可以覆盖它。

使用<a>上面HTML中的示例

var element = document.getElementById('testing');
element.onclick = function () { alert('did stuff #1'); };
element.onclick = function () { alert('did stuff #2'); };

...当您单击该元素时,您只会看到“第2件东西”-您onclick用第二个值覆盖了属性的第一个分配值,也覆盖了原始的内联HTML onclick属性。在此处查看:http : //jsfiddle.net/jpgah/

广义上讲,不要使用内联事件可能有特定的用例,但是如果您不是100%确信拥有该用例,那么您就不要也不应使用内联事件。

现代Javascript(Angular等)

自从最初发布此答案以来,像Angular这样的javascript框架已经变得越来越流行。您将在Angular模板中看到如下代码:

<button (click)="doSomething()">Do Something</button>

这看起来像一个内联事件,但事实并非如此。此类模板将转换为更复杂的代码,该代码在幕后使用事件侦听器。我在此处编写的有关事件的所有内容仍然适用,但是您至少要从一层坚硬的泥泞中解脱出来。您应该了解具体细节,但是,如果您的现代JS框架最佳实践涉及在模板中编写此类代码,那么您就不会觉得自己在使用内联事件-并非如此。

哪个最好?

问题是浏览器的兼容性和必要性。您是否需要将多个事件附加到一个元素?将来会吗?很有可能,你会的。attachEvent和addEventListener是必需的。如果不是这样,则内联事件似乎可以解决问题,但是为将来做准备更好,尽管看起来似乎不太可能,但至少可以预见。您有机会必须转向基于JS的事件侦听器,因此您最好从那里开始。不要使用内联事件。

jQuery和其他JavaScript框架在通用模型中封装了DOM 2级事件的不同浏览器实现,因此您可以编写跨浏览器兼容的代码,而不必担心IE作为反叛者的历史。与jQuery相同的代码,所有的跨浏览器都可以使用:

$(element).on('click', function () { /* do stuff */ });

但是,请不要用完并为此获得一个框架。您可以轻松地滚动自己的小实用程序来维护旧版浏览器:

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!'); }
);

试试看:http : //jsfiddle.net/bmArj/

考虑到所有这些因素,除非您正在查看的脚本以其他方式考虑了浏览器的差异(在您的问题中未显示的代码中),addEventListener否则使用的部分将不适用于低于9的IE版本。

文档和相关阅读

如果您还有其他几个功能,则可以看到的区别:

var h = document.getElementById('a');
h.onclick = doThing_1;
h.onclick = doThing_2;

h.addEventListener('click', doThing_3);
h.addEventListener('click', doThing_4);

功能2、3和4有效,但功能1不起作用。这是因为addEventListener不会覆盖现有的事件处理程序,而是onclick覆盖任何现有的onclick = fn事件处理程序。

当然,另一个显着的区别是,onclick它将始终有效,而addEventListener在版本9之前的Internet Explorer中不起作用。您可以在IE <9中使用类似的语法attachEvent语法稍有不同)。

在这个答案中,我将描述定义DOM事件处理程序的三种方法。

element.addEventListener()

代码示例:

element.addEventListener() 具有多个优点:

  • 允许您注册无限的事件处理程序并使用删除它们element.removeEventListener()
  • 具有useCapture参数,它指示您是要在捕获阶段还是冒泡阶段中处理事件请参阅:无法理解addEventListener中的useCapture属性
  • 关心语义基本上,它使注册事件处理程序更加明确。对于一个初学者来说,函数调用使得它明显的事情发生,而对DOM元素的某些属性分配事件,至少不直观。
  • 使您可以分隔文档结构(HTML)和逻辑(JavaScript)在小型Web应用程序中,这似乎无关紧要,但是对于任何更大的项目而言,它至关重要。维护一个将结构和逻辑分开的项目要比不保留一个项目的方法容易得多。
  • 消除混淆与正确的事件名称。由于使用内联事件侦听器或将事件侦听器分配给.oneventDOM元素的属性,因此许多经验不足的JavaScript程序员都认为事件名称是例如onclickonloadon不是事件名称的一部分正确的事件名称是clickand load,这就是将事件名称传递给的方式.addEventListener()
  • 几乎所有浏览器均可使用如果仍然需要支持IE <= 8,则可以使用MDN中的polyfill

element.onevent = function() {}(例如onclickonload

代码示例:

这是在DOM 0中注册事件处理程序的方法。现在不建议这样做,因为它:

  • 允许您注册一个事件处理程序。同样,删除分配的处理程序也不是很直观,因为要删除使用此方法分配的事件处理程序,您必须将onevent属性还原回其初始状态(即null)。
  • 对错误的响应正确。例如,如果您错误地将字符串分配给window.onload,例如:window.onload = "test";,则不会抛出任何错误。您的代码无法正常工作,很难找出原因。.addEventListener()但是,会引发错误(至少在Firefox中如此):TypeError:EventTarget.addEventListener的参数2不是object
  • 没有提供选择要在捕获或冒泡阶段处理事件的方法。

内联事件处理程序(oneventHTML属性)

代码示例:

与相似element.onevent,现在不建议使用。除了存在的问题外element.onevent,它:

  • 是一个潜在的安全问题,因为它使XSS更具危害性。如今,网站应发送适当的Content-Security-PolicyHTTP标头以阻止内联脚本,并仅允许来自受信任域的外部脚本。请参阅内容安全策略如何工作?
  • 分开文件的结构和逻辑
  • 如果使用服务器端脚本生成页面,并且例如生成一百个链接,每个链接都具有相同的内联事件处理程序,则与仅定义一次事件处理程序的代码相比,您的代码将更长。这意味着客户端将必须下载更多内容,结果您的网站将变慢。

也可以看看

虽然onclick在所有浏览器中都可以使用,addEventListener但在旧版本的Internet Explorer中却不能使用,而只能使用它attachEvent

缺点onclick是只能有一个事件处理程序,而其他两个将触发所有已注册的回调。

据我所知,DOM“加载”事件仍然只在非常有限的范围内起作用。这意味着它只会火了window objectimages<script>例如元素。直接onload分配也是如此。两者之间没有技术上的区别。可能.onload =具有更好的跨浏览器可用性。

但是,您不能将a分配load event<div><span>元素或其他。

摘要:

  1. addEventListener可以添加多个事件,而onclick不能这样做。
  2. onclick可以作为HTML属性添加,而addEventListener只能在<script>元素内添加
  3. addEventListener 可以采用第三个参数来停止事件传播。

两者都可以用来处理事件。但是,addEventListener应该优先选择它,因为它可以做onclick 更多的事情不要将内联onclick用作HTML属性,因为这会将javascript和HTML混合在一起,这是一种不好的做法。它使代码的可维护性降低。

有一个细节没有注意到尚:现代桌面浏览器考虑不同的按键操作是“点击”了AddEventListener('click',并onclick在默认情况下。

  • 在Chrome 42和IE11,双方onclickAddEventListener单击火左边和中间点击。
  • 在Firefox 38,onclick触发在左侧点击,但AddEventListener点击左,中火右点击。

另外,当涉及滚动游标时,在浏览器之间的中单击行为也非常不一致:

  • 在Firefox上,总是会触发中点击事件。
  • 在Chrome上,如果Middleclick打开或关闭滚动光标,它们将不会触发。
  • 在IE上,当滚动光标关闭时会触发,但在打开时不会触发。

还值得注意的是,任何键盘可选择的HTML元素的“ click”事件,例如input在选定元素时也会在空间上触发或进入。

Javascript倾向于将所有内容混合到对象中,这可能会造成混淆。JavaScript的方式合而为一。

本质上,onclick是HTML属性。相反,addEventListener是DOM对象上表示HTML元素的方法。

在JavaScript对象中,方法仅仅是一个具有作为值的函数的属性,并且该属性与它所附加的对象一起工作(例如,使用此方法)。

在JavaScript中,以DOM表示的HTML元素会将其属性映射到其属性。

这是人们感到困惑的地方,因为JavaScript将所有内容融合到一个没有间接层的单个容器或名称空间中。

在普通的OO布局中(至少会合并属性/方法的命名空间),您可能会遇到以下情况:

domElement.addEventListener // Object(Method)
domElement.attributes.onload // Object(Property(Object(Property(String))))

有一些变化,例如可以使用getter / setter进行onload或使用HashMap进行属性转换,但是最终看起来就是这样。JavaScript期望知道什么是其他东西,从而消除了该间接层。它将domElement和属性合并在一起。

除非兼容性,否则最佳做法是使用addEventListener。当其他答案谈论这方面的差异而不是基本的程序差异时,我将放弃它。本质上,在理想的世界中,您实际上只打算在HTML上使用on *,但在更理想的世界中,您不应该在HTML中进行类似的操作。

为什么今天占主导地位?它编写起来更快,更容易学习并且往往可以正常工作。

HTML的整个加载重点是首先提供对addEventListener方法或功能的访问。通过在JS中使用它,您可以直接使用HTML。

假设您可以设置自己的属性:

$('[myclick]').each(function(i, v) {
     v.addEventListener('click', function() {
         eval(v.myclick); // eval($(v).attr('myclick'));
     });
});

JS所做的与此有所不同。

您可以将其等同为(对于创建的每个元素):

element.addEventListener('click', function() {
    switch(typeof element.onclick) {
          case 'string':eval(element.onclick);break;
          case 'function':element.onclick();break;
     }
});

实际的实现细节可能会随一系列细微的变化而有所不同,从而使两者在某些情况下略有不同,但这就是要点。

可以说是一个兼容性黑客,您可以将函数固定到on属性,因为默认情况下属性都是字符串。

根据MDN,差异如下:

addEventListener:

EventTarget.addEventListener()方法将指定的EventListener兼容对象添加到事件侦听器列表中,以在其调用的EventTarget上指定事件类型。事件目标可以是文档中的Element,文档本身,Window或支持事件的任何其他对象(例如XMLHttpRequest)。

onclick:

onclick属性返回当前元素上的click事件处理程序代码。使用click事件触发动作时,还应考虑将相同动作添加到keydown事件中,以允许不使用鼠标或触摸屏的人使用相同动作。语法element.onclick = functionRef; 其中functionRef是函数-通常是在其他地方声明的函数的名称或函数表达式。有关详细信息,请参见“ JavaScript指南:函数”。

如下面的代码所示,在语法上也有区别:

addEventListener:

// Function to change the content of t2
function modifyText() {
  var t2 = document.getElementById("t2");
  if (t2.firstChild.nodeValue == "three") {
    t2.firstChild.nodeValue = "two";
  } else {
    t2.firstChild.nodeValue = "three";
  }
}

// add event listener to table
var el = document.getElementById("outside");
el.addEventListener("click", modifyText, false);

onclick:

function initElement() {
    var p = document.getElementById("foo");
    // NOTE: showAlert(); or showAlert(param); will NOT work here.
    // Must be a reference to a function name, not a function call.
    p.onclick = showAlert;
};

function showAlert(event) {
    alert("onclick Event detected!");
}

如果您不太担心浏览器的支持,则可以使用一种方法在事件调用的函数中重新绑定“ this”引用。通常,它将在执行函数时指向生成事件的元素,而这并非总是您想要的。棘手的部分是要同时能够删除完全相同的事件侦听器,如本例所示:http : //jsfiddle.net/roenbaeck/vBYu3/

/*
    Testing that the function returned from bind is rereferenceable, 
    such that it can be added and removed as an event listener.
*/
function MyImportantCalloutToYou(message, otherMessage) {
    // the following is necessary as calling bind again does 
    // not return the same function, so instead we replace the 
    // original function with the one bound to this instance
    this.swap = this.swap.bind(this); 
    this.element = document.createElement('div');
    this.element.addEventListener('click', this.swap, false);
    document.body.appendChild(this.element);
}
MyImportantCalloutToYou.prototype = {
    element: null,
    swap: function() {
        // now this function can be properly removed 
        this.element.removeEventListener('click', this.swap, false);           
    }
}

上面的代码在Chrome中运行良好,并且可能使“绑定”与其他浏览器兼容。

使用内联处理程序与内容安全策略不兼容,因此addEventListener从该角度来看,方法更加安全。当然,您可以使用启用内联处理程序,unsafe-inline但是,顾名思义,这样做并不安全,因为它会带回CSP阻止的所有JavaScript开发。

element.onclick = function(){/ *做事* /}

element.addEventListener('click',function(){/ *做东西* /},false);

他们显然做同样的事情:监听click事件并执行回调函数。但是,它们并不等效。如果您需要在两者之间进行选择,这可以帮助您确定哪一个最适合您。

主要区别在于onclick只是一个属性,并且像所有对象属性一样,如果您多次写入,它将被覆盖使用addEventListener()代替,我们可以简单地将事件处理程序绑定到该元素,并且可以在每次需要它时调用它,而不必担心任何被覆盖的属性。这里显示示例,

试试看:https : //jsfiddle.net/fjets5z4/5/

首先,我很想继续使用onclick,因为它更短,看起来更简单……实际上是这样。但我不建议再使用它。就像使用内联JavaScript。如今,强烈建议不要使用内联JavaScript之类的东西(也不鼓励内联CSS,但这是另一个主题)。

但是,尽管是标准功能,但addEventListener()函数在旧的浏览器(版本9以下的Internet Explorer)中不起作用,这是另一个很大的不同。如果需要支持这些古老的浏览器,则应遵循onclick方式。但是,您也可以使用jQuery(或其替代方案之一):它基本上简化了工作并减少了浏览器之间的差异,因此可以节省大量时间。

var clickEvent = document.getElementByID("onclick-eg");
var EventListener = document.getElementByID("addEventListener-eg");

clickEvent.onclick = function(){
    window.alert("1 is not called")
}
clickEvent.onclick = function(){
    window.alert("2 is not called")
}

EventListener.addEventListener("click",function(){
    window.alert("1 is called")
})
EventListener.addEventListener("click",function(){
    window.alert("2 is also called")
})

也可以通过对原型进行扩展来扩展侦听器(如果我们具有对它的引用,而不是其匿名函数),或者使onclick调用成为对函数库的调用(调用其他函数的函数)。

喜欢:

elm.onclick = myFunctionList;
function myFunctionList(){
    myFunc1();
    myFunc2();
}

这意味着我们不必更改onclick调用就可以更改函数myFunctionList()以完成我们想要的任何事情,但这使我们无法控制冒泡/捕获阶段,因此对于较新的浏览器应避免使用。

addEventListener 可让您设置多个处理程序,但IE8或更低版本不支持。

IE确实有attachEvent,但并不完全相同。

'this'JavasSript中关键字引用的上下文不同。

看下面的代码:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>

</head>
<body>
    <input id="btnSubmit" type="button" value="Submit" />
    <script>
        function disable() {
            this.disabled = true;
        }
        var btnSubmit = document.getElementById('btnSubmit');
        btnSubmit.onclick = disable();
        //btnSubmit.addEventListener('click', disable, false);
    </script>
</body>
</html>

它的作用确实很简单。当您单击该按钮时,该按钮将被自动禁用。

首先,当您尝试以这种方式连接button.onclick = function(),
事件时,将通过单击按钮来触发onclick事件,但是,由于在button.onclick和onclick事件处理程序之间没有显式绑定,因此不会禁用该按钮。
如果您调试看到
'this'对象,则可以看到它指向'window'对象。

其次,如果您注释btnSubmit.onclick = disable();和取消注释
,则
//btnSubmit.addEventListener('click', disable, false);可以看到该按钮被禁用,因为通过这种方式,button.onclick事件和onclick事件处理程序之间存在显式绑定。如果您调试到禁用功能,则可以看到'this'指向button control而不是window

这是我不喜欢JavaScript的不一致之处。顺便说一句,如果您使用的是jQuery($('#btnSubmit').on('click', disable);),它将使用显式绑定。

onclick本质上是一个addEventListener,它在单击元素时专门执行一个功能。因此,当您具有执行简单操作的按钮(例如计算器按钮)时很有用。addEventlistener可用于多种操作,例如在加载DOM或所有内容时执行操作,类似于window.onload,但具有更多控制权。

请注意,实际上,您可以内联使用多个事件,或者至少可以通过使用分号(如分号)分隔每个函数来使用onclick,例如...。

我不会用内联函数编写函数,因为以后可能会出现问题,而且imo会很乱。只需使用它来调用脚本文件中已完成的功能。

我想您使用哪一种取决于您想要的。addEventListener用于复杂操作,onclick用于简单操作。我已经看到一些项目没有将特定项目附加到元素上,而是实现了一个更具全局性的事件侦听器,该事件侦听器将确定是否在按钮上轻击,并根据所按的内容执行某些任务。Imo可能会引发我认为的问题,尽管该事件侦听器必须处理每一次点击,但可能很小,但可能会浪费资源

本文地址:http://javascript.askforanswer.com/addeventlisteneryuonclick.html
文章标签: ,   ,  
版权声明:本文为原创文章,版权归 javascript 所有,欢迎分享本文,转载请保留出处!

文件下载

老薛主机终身7折优惠码boke112

上一篇:
下一篇:

评论已关闭!