code

addEventListener 대 onclick

codestyles 2020. 10. 2. 22:20
반응형

addEventListener 대 onclick


addEventListener의 차이점은 무엇입니까 onclick?

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

위의 코드는 별도의 .js 파일에 함께 있으며 둘 다 완벽하게 작동합니다.


둘 다 정확하지만 그들 중 어느 것도 그 자체로 "최고"가 아니며 개발자가 두 가지 방법을 모두 사용하기로 선택한 이유가있을 수 있습니다.

이벤트 리스너 (addEventListener 및 IE의 attachEvent)

이전 버전의 Internet Explorer는 거의 모든 다른 브라우저와는 다르게 자바 스크립트를 구현합니다. 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 ] 사용을 나타냅니다 . 함수 참조 [ doc ] 또는 클로저 [ doc ]를 사용하여 이벤트 리스너를 추가 할 수도 있습니다 .

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

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

의 또 다른 중요한 기능은 addEventListener리스너가 버블 링 이벤트 [ doc ]에 반응하는 방식을 제어하는 ​​final 매개 변수 입니다. 나는 예제에서 거짓을 전달했는데, 아마 95 %의 사용 사례에서 표준입니다. attachEvent, 또는 인라인 이벤트를 사용할 때에 해당하는 인수가 없습니다 .

인라인 이벤트 (HTML onclick = ""속성 및 element.onclick)

자바 스크립트를 지원하는 모든 브라우저에서 이벤트 리스너를 인라인으로 배치 할 수 있습니다. 즉, HTML 코드에서 바로 사용할 수 있습니다. 아마도 이것을 본 적이있을 것입니다.

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

대부분의 숙련 된 개발자는이 방법을 사용하지 않지만 작업을 완료합니다. 간단하고 직접적입니다. 여기에서 클로저 나 익명 함수를 사용할 수 없으며 (처리기 자체가 일종의 익명 함수 임에도 불구하고) 범위 제어가 제한됩니다.

언급 한 다른 방법 :

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

... 범위를 더 많이 제어 할 수 있고 (HTML이 아닌 스크립트를 작성하기 때문에) 익명 함수, 함수 참조 및 / 또는 클로저를 사용할 수 있다는 점을 제외하면 인라인 자바 스크립트와 동일합니다.

인라인 이벤트의 중요한 단점은 위에서 설명한 이벤트 리스너와 달리 인라인 이벤트가 하나만 할당 될 수 있다는 것입니다. 인라인 이벤트는 요소 [ doc ] 의 속성 / 속성으로 저장되므로 덮어 쓸 수 있습니다.

<a>위 HTML 의 예 사용하여 :

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

... 요소를 클릭하면 "Did stuff # 2" 표시됩니다. onclick속성 의 첫 번째 할당을 두 번째 값으로 덮어 썼고 원래 인라인 HTML onclick속성도 덮어 썼습니다 . 여기에서 확인하세요 : http://jsfiddle.net/jpgah/ .

일반적으로 인라인 이벤트를 사용하지 마십시오 . 특정 사용 사례가있을 수 있지만 해당 사용 사례가 있는지 100 % 확신하지 못하는 경우 인라인 이벤트를 사용하지 않으며 사용해서는 안됩니다.

최신 자바 스크립트 (Angular 등)

이 답변이 원래 게시 된 이후로 Angular와 같은 자바 스크립트 프레임 워크가 훨씬 더 인기를 얻었습니다. Angular 템플릿에서 다음과 같은 코드를 볼 수 있습니다.

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

인라인 이벤트처럼 보이지만 그렇지 않습니다. 이 유형의 템플릿은 뒤에서 이벤트 리스너를 사용하는 더 복잡한 코드로 변환됩니다. 여기서 이벤트에 대해 작성한 모든 내용은 여전히 ​​적용되지만 적어도 하나의 레이어에 의해 핵심에서 제거됩니다. 기본적으로 이해해야하지만 최신 JS 프레임 워크 모범 사례가 템플릿에 이러한 종류의 코드를 작성하는 것과 관련이 있다면 인라인 이벤트를 사용하는 것처럼 느끼지 마세요. 그렇지 않습니다.

어느 것이 최고입니까?

문제는 브라우저 호환성과 필요성의 문제입니다. 요소에 둘 이상의 이벤트를 첨부해야합니까? 당신은 미래에? 확률은 당신이 할 것입니다. attachEvent 및 addEventListener가 필요합니다. 그렇지 않은 경우 인라인 이벤트가 트릭을 수행하는 것처럼 보일 수 있지만 가능성은 낮지 만 적어도 예측할 수있는 미래를 준비하는 것이 훨씬 좋습니다. JS 기반 이벤트 리스너로 이동해야 할 가능성이 있으므로 여기서 시작하는 것이 좋습니다. 인라인 이벤트를 사용하지 마십시오.

jQuery 및 기타 자바 스크립트 프레임 워크는 일반 모델에서 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()

코드 예 :

const element = document.querySelector('a');
element.addEventListener('click', event => event.preventDefault(), true);
<a href="//google.com">Try clicking this link.</a>

element.addEventListener() 여러 가지 장점이 있습니다.

  • 무제한 이벤트 핸들러 를 등록 하고 element.removeEventListener().
  • 가지고 useCapture당신은 그것에서 이벤트를 처리할지 여부를 나타내는 매개 변수를 캡처 또는 버블 링 단계를 . 참조 : addEventListener의 useCapture 속성을 이해할 수 없습니다 .
  • 의미론에 관심이 있습니다. 기본적으로 이벤트 핸들러를보다 명시 적으로 등록합니다. 초보자의 경우 함수 호출을 통해 어떤 일이 발생 했음을 분명히 알 있지만 DOM 요소의 일부 속성에 이벤트를 할당하는 것은 적어도 직관적이지 않습니다.
  • 문서 구조 (HTML)와 로직 (JavaScript)분리 할 수 있습니다 . 작은 웹 응용 프로그램에서는 중요하지 않은 것처럼 보일 수 있지만 더 큰 프로젝트 에서는 중요합니다. 구조와 논리를 분리하는 프로젝트를 유지하지 않는 프로젝트보다 유지하는 것이 훨씬 쉽습니다.
  • 올바른 이벤트 이름과의 혼동을 제거합니다. 인라인 이벤트 리스너를 사용하거나 .oneventDOM 요소의 속성에 이벤트 리스너를 할당하기 때문에 경험이 부족한 많은 JavaScript 프로그래머는 이벤트 이름이 예를 들어 onclick또는 onload. 이벤트 이름의 일부 on아닙니다 . 올바른 이벤트 이름은 click및이며 load, 이것이 이벤트 이름이에 전달되는 방식 .addEventListener()입니다.
  • 거의 모든 브라우저 에서 작동 합니다 . 여전히 IE <= 8을 지원해야하는 경우 MDN의 polyfill을 사용할 수 있습니다 .

element.onevent = function() {}(예 : onclick, onload)

코드 예 :

const element = document.querySelector('a');
element.onclick = event => event.preventDefault();
<a href="//google.com">Try clicking this link.</a>

이것은 DOM 0에서 이벤트 핸들러를 등록하는 방법이었습니다. 다음과 같은 이유로 권장되지 않습니다.

  • 하나의 이벤트 핸들러 등록 할 수 있습니다 . 또한 할당 된 핸들러를 제거하는 것은 직관적이지 않습니다.이 메서드를 사용하여 할당 된 이벤트 핸들러를 제거하려면 onevent속성을 초기 상태 (예 :)로 되돌려 야 하기 때문 null입니다.
  • 오류에 적절하게 응답 하지 않습니다 . 예를 들어 실수로에 문자열을 할당 한 경우 ( window.onloadwindow.onload = "test";:) 오류가 발생하지 않습니다. 코드가 작동하지 않고 그 이유를 찾기가 정말 어려울 것입니다. .addEventListener()그러나 오류가 발생합니다 (적어도 Firefox에서는) : TypeError : EventTarget.addEventListener의 Argument 2 is not an object .
  • 캡처 또는 버블 링 단계에서 이벤트를 처리할지 여부를 선택할 수있는 방법을 제공하지 않습니다.

인라인 이벤트 핸들러 ( oneventHTML 속성)

코드 예 :

<a href="//google.com" onclick="event.preventDefault();">Try clicking this link.</a>

와 마찬가지로 element.onevent이제 권장하지 않습니다. element.onevent가지고 있는 문제 외에도 :

  • A는 잠재적 인 보안 문제 가 XSS 훨씬 더 해로운 수 있기 때문에. 오늘날 웹 사이트는 적절한 Content-Security-PolicyHTTP 헤더를 보내 인라인 스크립트를 차단하고 신뢰할 수있는 도메인의 외부 스크립트 만 허용해야합니다. 콘텐츠 보안 정책어떻게 작동합니까?를 참조하십시오 .
  • 문서 구조와 로직을 분리 하지 않습니다 .
  • 서버 측 스크립트를 사용하여 페이지를 생성하고 예를 들어 각각 동일한 인라인 이벤트 처리기를 사용하는 100 개의 링크를 생성하면 이벤트 처리기가 한 번만 정의 된 경우보다 코드가 훨씬 길어집니다. 즉, 클라이언트는 더 많은 콘텐츠를 다운로드해야하고 결과적으로 웹 사이트 속도가 느려집니다.

또한보십시오


onclick모든 브라우저에서 작동 하지만 대신 addEventListener사용 attachEvent하는 이전 버전의 Internet Explorer에서는 작동하지 않습니다 .

단점은 onclick하나의 이벤트 핸들러 만있을 수 있고 다른 두 개는 등록 된 모든 콜백을 실행한다는 것입니다.


내가 아는 한, DOM "로드"이벤트는 여전히 매우 제한적으로 작동합니다. window object, 예를 들어 , images<script>요소에 대해서만 실행됩니다 . 직접 onload할당도 마찬가지 입니다. 이 둘 사이에는 기술적 차이가 없습니다. 아마도 .onload =브라우저 간 가용성이 더 좋을 입니다.

그러나, 당신은을 할당 할 수 없습니다 load eventA를 <div>또는 <span>요소 또는 이것 저것.


요약:

  1. addEventListener여러 이벤트를 추가 할 onclick수 있지만이 작업은 수행 할 수 없습니다.
  2. onclick can be added as an HTML attribute, whereas an addEventListener can only be added within <script> elements.
  3. addEventListener can take a third argument which can stop the event propagation.

Both can be used to handle events. However, addEventListener should be the preferred choice since it can do everything onclick does and more. Don't use inline onclick as HTML attributes as this mixes up the javascript and the HTML which is a bad practice. It makes the code less maintainable.


One detail hasn't been noted yet: modern desktop browsers consider different button presses to be "clicks" for AddEventListener('click' and onclick by default.

  • On Chrome 42 and IE11, both onclick and AddEventListener click fire on left and middle click.
  • On Firefox 38, onclick fires only on left click, but AddEventListener click fires on left, middle and right clicks.

Also, middle-click behavior is very inconsistent across browsers when scroll cursors are involved:

  • On Firefox, middle-click events always fire.
  • On Chrome, they won't fire if the middleclick opens or closes a scroll cursor.
  • On IE, they fire when scroll cursor closes, but not when it opens.

It is also worth noting that "click" events for any keyboard-selectable HTML element such as input also fire on space or enter when the element is selected.


According to MDN, the difference is as below:

addEventListener:

The EventTarget.addEventListener() method adds the specified EventListener-compatible object to the list of event listeners for the specified event type on the EventTarget on which it's called. The event target may be an Element in a document, the Document itself, a Window, or any other object that supports events (such as XMLHttpRequest).

onclick:

The onclick property returns the click event handler code on the current element. When using the click event to trigger an action, also consider adding this same action to the keydown event, to allow the use of that same action by people who don't use a mouse or a touch screen. Syntax element.onclick = functionRef; where functionRef is a function - often a name of a function declared elsewhere or a function expression. See "JavaScript Guide:Functions" for details.

There is also a syntax difference in use as you see in the below codes:

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

If you are not too worried about browser support, there is a way to rebind the 'this' reference in the function called by the event. It will normally point to the element that generated the event when the function is executed, which is not always what you want. The tricky part is to at the same time be able to remove the very same event listener, as shown in this example: 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);           
    }
}

The code above works well in Chrome, and there's probably some shim around making "bind" compatible with other browsers.


Using inline handlers is incompatible with Content Security Policy so the addEventListener approach is more secure from that point of view. Of course you can enable the inline handlers with unsafe-inline but, as the name suggests, it's not safe as it brings back the whole hordes of JavaScript exploits that CSP prevents.


It should also be possible to either extend the listener by prototyping it (if we have a reference to it and its not an anonymous function) -or make the 'onclick' call a call to a function library (a function calling other functions)

like

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

this means we never has to chenge the onclick call just alter the function myFunctionList() to do what ever we want, but this leave us without control of bubbling/catching phases so should be avoided for newer browsers.

just in case someone find this thread in the future...


addEventListener lets you set multiple handlers, but isn't supported in IE8 or lower.

IE does have attachEvent, but it's not exactly the same.


The context referenced by 'this' keyword in JavasSript is different.

look at the following code:

<!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>

What it does is really simple. when you click the button, the button will be disabled automatically.

First when you try to hook up the events in this way button.onclick = function(), onclick event will be triggered by clicking the button, however, the button will not be disabled because there's no explicit binding between button.onclick and onclick event handler. If you debug see the 'this' object, you can see it refers to 'window' object.

Secondly, if you comment btnSubmit.onclick = disable(); and uncomment //btnSubmit.addEventListener('click', disable, false); you can see that the button is disabled because with this way there's explicit binding between button.onclick event and onclick event handler. If you debug into disable function, you can see 'this' refers to the button control rather than the window.

This is something I don't like about JavaScript which is inconsistency. Btw, if you are using jQuery($('#btnSubmit').on('click', disable);), it uses explicit binding.


Javascript tends to blend everything into objects and that can make it confusing. All into one is the JavaScript way.

Essentially onclick is a HTML attribute. Conversely addEventListener is a method on the DOM object representing a HTML element.

In JavaScript objects, a method is merely a property that has a function as a value and that works against the object it is attached to (using this for example).

In JavaScript as HTML element represented by DOM will have it's attributes mapped onto its properties.

This is where people get confused because JavaScript melds everything into a single container or namespace with no layer of indirection.

In a normal OO layout (which does at least merge the namespace of properties/methods) you would might have something like:

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

There are variations like it could use a getter/setter for onload or HashMap for attributes but ultimately that's how it would look. JavaScript eliminated that layer of indirection at the expect of knowing what's what among other things. It merged domElement and attributes together.

Barring compatibility you should as a best practice use addEventListener. As other answers talk about the differences in that regard rather than the fundamental programmatic differences I will forgo it. Essentially, in an ideal world you're really only meant to use on* from HTML but in an even more ideal world you shouldn't be doing anything like that from HTML.

Why is it dominant today? It's quicker to write, easier to learn and tends to just work.

The whole point of onload in HTML is to give access to the addEventListener method or functionality in the first place. By using it in JS you're going through HTML when you could be applying it directly.

Hypothetically you can make your own attributes:

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

What JS does with is a bit different to that.

You can equate it to something like (for every element created):

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

실제 구현 세부 사항은 미묘한 변형 범위에 따라 다를 수 있으므로 경우에 따라 두 가지가 약간 다를 수 있지만 그게 요점입니다.

기본적으로 속성은 모두 문자열이기 때문에 함수를 on 속성에 고정 할 수있는 호환성 해킹입니다.

참고 URL : https://stackoverflow.com/questions/6348494/addeventlistener-vs-onclick

반응형