본문 바로가기
JavaScript

JavaScript] DOM events, Event handler, addEventListener

by Fastlane 2022. 11. 22.
728x90
반응형

출처 : https://javascript.info/introduction-browser-events

'이벤트'란 무언가 발생했다는 신호이다. 

Mouse events

  • click
  • contextmenu
  • mouseover/mouseout
  • mousedown/mouseup
  • mousemove

Keyboard events

  • keydown/keyup

Form element events

  • submit
  • focus

Document events

  • DOMContentLoaded - DOM전체 생성 시

CSS events

  • transitioned - CSS-animation 종료 시

Event handlers

event에 반응하기 위해, handler(event발생 시, 실행하는 함수)를 할당한다. 

handler할당에 여러 방법이 있다. 

HTML-attribute

on<event> attribute로 HTML에 세팅할 수 있다. 

<input value="Click me" onclick="alert('Click!')" type="button">

마우스 클릭하면, onlick이 실행된다. onclick은 double quotes로 감싸져 있어서 내부 코드는 '(single quotes)만 사용한다. HTML-attribute는 많은 양의 코드를 작성하기 어려우므로, JavaScript함수를 작성하고 호출하는 것이 낫다. 

DOM property

DOM property인 on<event>을 사용하여 handler를 할당할 수 있다. 

HTML-attribute에 handler가 있는 경우, browser가 읽고 함수를 만들어 DOM property에 작성한다. 따라서 HTML-attribute와 DOM property는 사실 동일하게 동작한다. 

<input type="button" id="button" value="Button">
<script>
  button.onclick = function() {
    alert('Click!');
  };
</script>

onlick property는 오직 하나이다.

<input type="button" id="elem" onclick="alert('Before')" value="Click me">
<script>
  elem.onclick = function() { // 기존의 handler를 overwrite한다. 
    alert('After'); // only this will be shown
  };
</script>

 handler를 삭제하기 위해서는 elem.onclick = null 처리한다. 

 

Accessing the element: this

handler의 this는 handler가 할당된 element이다. 

click시, 'Click me' text를 alert한다. 

<button onclick="alert(this.innerHTML)">Click me</button>

Possible mistakes

events를 사용하면서 할 수 있는 실수들을 알아보자. 

 

존재하는 함수를 handler로 설정할 수 있다. 

function sayThanks() {
  alert('Thanks!');
}

// right
button.onclick = sayThanks;

// wrong
button.onclick = sayThanks();

괄호를 추가하면, sayThanks()는 함수호출이된다. 따라서 마지막 줄은 함수실행의 결과를 받으며 undefined가 된다. 

반면에 markup에서는 괄호가 필요하다. 

<input type="button" id="button" onclick="sayThanks()">

차이점은 browser가 attribute를 읽을때 handler 함수를 생성한다. 

button.onclick = function() {
  sayThanks(); // <-- the attribute content goes here
};

 handler 설정 시, setAttribute를 사용하지 않는다. 동작하지 않는다. 

// a click on <body> will generate errors,
// because attributes are always strings, function becomes a string
document.body.setAttribute('onclick', function() { alert(1) });

DOM-property는 case-sensitive하므로 elem.onclick 으로 설정한다. 

addEventListener

앞서 언급한 handler 설정방법의 문제는 하나의 event에 multiple handler를 설정할 수 없다는 점이다. 

예를들어, 코드의 한 부분에서는 버튼 클릭시 highlight하고, 다른데서는 동일한 버튼 클릭시 메시지를 보여주려고 한다.  

2개의 event handler를 설정하면, overwrite된다. addEventListener, removeEventListener 함수를 사용하여 handlers를 관리할 수 있다. 

element.addEventListener(event, handler, [options]);

event : Event name

handler : handler function

options : 

  • once : true이면 trigger된 이후 listener는 자동으로 삭제된다. 
  • capture : 
  • passive : true이면 handler는 preventDefault()를 호출하지 않는다. 

handler를 삭제하기 위해서 동일한 함수를 전달해야 한다. 

//아래 소스는 동작하지 않는다. 동일한 코드지만, 다른 함수 객체이다. 
elem.addEventListener( "click" , () => alert('Thanks!'));
// ....
elem.removeEventListener( "click", () => alert('Thanks!'));

아래가 올바른 방법이다. 함수를 변수로 저장하지 않으면 제거할 수 없다. 

function handler() {
  alert( 'Thanks!' );
}

input.addEventListener("click", handler);
// ....
input.removeEventListener("click", handler);
<input id="elem" type="button" value="Click me"/>

<script>
  function handler1() {
    alert('Thanks!');
  };

  function handler2() {
    alert('Thanks again!');
  }

  elem.onclick = () => alert("Hello");
  elem.addEventListener("click", handler1); // Thanks!
  elem.addEventListener("click", handler2); // Thanks again!
</script>

Event object

event에 대해 자세히 알아보자. 

event가 발생될 때, 브라우저는 event object를 생성하고 상세내용을 입력한 후, handler에 argument로 전달한다. 

<input type="button" value="Click me" id="elem">

<script>
  elem.onclick = function(event) {
    // show event type, element and coordinates of the click
    alert(event.type + " at " + event.currentTarget);
    alert("Coordinates: " + event.clientX + ":" + event.clientY);
  };
</script>

event.type : Event type, 여기서는 click 이다. 

event.currentTarget : event를 handle하는 element이다. this와 동일하다. 

event object는 HTML handler에도 유효하다. 

<input type="button" onclick="alert(event.type)" value="Event type">

browser가 attribute를 읽으면 function(event){alert(event.type)}과 같은 함수를 생성한다. 

Object handlers: handleEvent

addEventListener를 사용하여 event handler에 함수가 아닌 object도 할당이 가능하다. event발생 시, 그것의 handleEvent 함수가 호출된다. 

<button id="elem">Click me</button>

<script>
  let obj = {
    handleEvent(event) {
      alert(event.type + " at " + event.currentTarget);
    }
  };

  elem.addEventListener('click', obj);
</script>

addEventListener가 handler로 object를 전달 받았을 때, obj.handleEvent(event)가 호출된다. 

custom class를 사용할 수도 있다. 

<button id="elem">Click me</button>

<script>
  class Menu {
    handleEvent(event) {
      switch(event.type) {
        case 'mousedown':
          elem.innerHTML = "Mouse button pressed";
          break;
        case 'mouseup':
          elem.innerHTML += "...and released.";
          break;
      }
    }
  }

  let menu = new Menu();

  elem.addEventListener('mousedown', menu);
  elem.addEventListener('mouseup', menu);
</script>

두 이벤트를 동일한 object가 handle한다. handleEvent 함수가 모든 소스를 가질 필요 없다. 아래와 같이 event-specific함수를 호출하도록 수정할 수 있다. 

<button id="elem">Click me</button>

<script>
  class Menu {
    handleEvent(event) {
      // mousedown -> onMousedown
      let method = 'on' + event.type[0].toUpperCase() + event.type.slice(1);
      this[method](event);
    }

    onMousedown() {
      elem.innerHTML = "Mouse button pressed";
    }

    onMouseup() {
      elem.innerHTML += "...and released.";
    }
  }

  let menu = new Menu();
  elem.addEventListener('mousedown', menu);
  elem.addEventListener('mouseup', menu);
</script>

event handler가 깔끔하게 나뉘어졌다. 

Summary

event handler를 설정하는 3가지 방법이 있다. 

  • HTML attribute : onclick="...", 최소한으로 사용하는 방법!
  • DOM property : elem.onclick = function.
  • Methods: addEventListener, removeEventListener, 가장 flexible하다. 

 

728x90
반응형

'JavaScript' 카테고리의 다른 글

Web APIs - Console API  (0) 2022.12.05
JavaScript] Event Bubbling and capturing  (0) 2022.11.23
JavaScript] Coordinates (element 좌표)  (0) 2022.11.17
JavaScript] Window sizes and scrolling  (0) 2022.11.14
JavaScript] Document Styles and classes  (1) 2022.11.14

댓글