Javascript

[Javascript] on 속성을 활용한 이벤트 등록과 ".EventListener" 정리

Rachel_ 2021. 12. 24. 15:39

Event (이벤트)

: 브라우저가 수행하거나 사용자가 수행하는 작업. 정적인 html 문서를 자바스크립트를 이용해 동적으로 바꿔주는 요소 중 하나라고 볼 수 있음.

 

html은 자바스크립트 코드를 활용해 이벤트 핸들러 속성(event handler attributes)을 html 요소(elements)에 추가할 수 있다.

 

Event Description
onclock 사용자가 html 요소를 클릭
onchange html 요소가 변경
onmouseover 사용자가 html 요소 위로 마우스를 이동
onmouseout 사용자가 html 요소에서 마우스를 이동
onkeydown 사용자가 키보드 키를 누름
onload 브라우저가 페이지 로드를 완료함

 

이벤트 핸들러 할당의 예시

 

1) input 이나 button 태그 안의 속성에 onclick 속성을 활용하여 할당하는 방법.

 

<script>
	funciton countcakes(){
    	for(let i=1; i<=3; i++){
        	alert("케이크 " + [i] + "조각");
            }
       }
    };
</script>

<button type="button" onclick="countcakes()" value="케이크는 몇개?">

 

2) DOM 프로퍼티 on<envent> 를 사용한 핸들러 할당.

<input id="count" type="button" value="숫자세기">
<script>
	count.onclick= function(){
    	alert("123");
    };
</script>

 

하지만 on 속성을 활용한 이벤트 할당은 1가지 밖에 불가능하며, 복수의 이벤트 핸들러는 할당할 수 없다.

 

addEventListener

문법

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

event : 이벤트의 이름

clock 사용자가 html 요소를 클릭
change html 요소가 변경
mouseover 사용자가 html 요소 위로 마우스를 이동
mouseout 사용자가 html 요소에서 마우스를 이동
keydown 사용자가 키보드 키를 누름
load 브라우저가 페이지 로드를 완료함

 

handler : 핸들러 함수 => 즉 내가 이벤트를 통해 출력하고자 혹은 변경하고자 하는 요소.

이 handler 는 function() 을 통해 함수나 객체화를 시킨 뒤에 활용해야 한다. 그렇지 않으면 addEventListener와 쌍을 이루는 removeEventListener에서 제거가 불가능해진다.

elem.addEventListener( "click" , () => alert('감사합니다!'));

elem.removeEventListener( "click", () => alert('감사합니다!'));

// 똑같아보이지만 문법적으로 함수가 다르기 때문에 remove가 작동하지 않는다.
// 따라서 function을 통해 함수를 만들어서 handler에 참조한다.

function handler() {
  alert( '감사합니다!' );
}

input.addEventListener("click", handler);
// ....
input.removeEventListener("click", handler);

 

options : 아래의 프로퍼티를 갖는 객체

  • once: true이면 이벤트가 트리거 될 때 리스너가 자동으로 삭제됩니다.
  • capture: 어느 단계에서 이벤트를 다뤄야 하는지를 알려주는 프로퍼티.
  • passive: true이면 리스너에서 지정한 함수가 preventDefault()를 호출하지 않습니다.

 

removeEventListener

문법

element.removeEventListener("event", handler, [options]);

 

이벤트 객체

이벤트를 제대로 다루려면 어떤 일이 일어났는지 상세히 알아야 합니다.

‘click’ 이벤트가 발생했다면 마우스 포인터가 어디에 있는지, ‘keydown’ 이벤트가 발생했다면 어떤 키가 눌렸는지 등에 대한 상세한 정보가 필요합니다.

이벤트가 발생하면 브라우저는 *이벤트 객체(event object)*라는 것을 만듭니다. 여기에 이벤트에 관한 상세한 정보를 넣은 다음, 핸들러에 인수 형태로 전달합니다.

아래는 이벤트 객체로부터 포인터 좌표 정보를 얻어내는 예시입니다.

<input type="button" value="클릭해 주세요." id="elem">

<script>
  elem.onclick = function(event) {
    // 이벤트 타입과 요소, 클릭 이벤트가 발생한 좌표를 보여줌
    alert(event.type + " 이벤트가 " + event.currentTarget + "에서 발생했습니다.");
    alert("이벤트가 발생한 곳의 좌표는 " + event.clientX + ":" + event.clientY +"입니다.");
  };
</script>
 

이벤트 객체에서 지원하는 프로퍼티 중 일부는 다음과 같습니다.

 

event.type

이벤트 타입, 위 예시에선 "click"

 

event.currentTarget

이벤트를 처리하는 요소. 화살표 함수를 사용해 핸들러를 만들거나 다른 곳에 바인딩하지 않은 경우엔 this가 가리키는 값과 같음, 화살표 함수를 사용했거나 함수를 다른 곳에 바인딩한 경우엔 event.currentTarget를 사용해 이벤트가 처리되는 요소 정보를 얻을 수 있음

 

event.clientX / event.clientY

포인터 관련 이벤트에서, 커서의 상대 좌표(모니터 기준 좌표가 아닌, 브라우저 화면 기준 좌표 – 옮긴이)

 

이 외에도 다양한 프로퍼티가 있습니다. 이벤트 타입에 따라 이벤트 객체에서 제공하는 프로퍼티는 다릅니다. 추후 다양한 종류의 이벤트를 학습하면서 이벤트별 프로퍼티에 대해서도 상세히 알아보겠습니다.

 

객체 형태의 핸들러와 handleEvent

addEventListener를 사용하면 함수뿐만 아니라 객체를 이벤트 핸들러로 할당할 수 있습니다. 이벤트가 발생하면 객체에 구현한 handleEvent 메서드가 호출됩니다.

<button id="elem">클릭해 주세요.</button>

<script>
  let obj = {
    handleEvent(event) {
      alert(event.type + " 이벤트가 " + event.currentTarget + "에서 발생했습니다.");
    }
  };

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

handlerEvent(event) 라는 함수 속의 event라는 변수값은 elem.addEventListener( 'click' ) 이라는 event 값이 가져온다.

 

보시다시피 addEventListener가 인수로 객체 형태의 핸들러를 받으면 이벤트 발생 시 obj.handleEvent(event)가 호출됩니다.

 

클래스를 사용할 수도 있습니다.

<button id="elem">클릭해 주세요.</button>

<script>
  class Menu {
    handleEvent(event) {
      switch(event.type) {
        case 'mousedown':
          elem.innerHTML = "마우스 버튼을 눌렀습니다.";
          break;
        case 'mouseup':
          elem.innerHTML += " 그리고 버튼을 뗐습니다.";
          break;
      }
    }
  }

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

위 예시에선 하나의 객체에서 두 개의 이벤트를 처리하고 있습니다. 이때 주의할 점은 addEventListener를 사용할 때는 요소에 타입을 정확히 명시해 주어야 한다는 점입니다. 위 예시에서 menu 객체는 오직 mousedown  mouseup이벤트에만 응답하고, 다른 타입의 이벤트에는 응답하지 않습니다.

 

handleEvent 메서드가 모든 이벤트를 처리할 필요는 없습니다. 이벤트 관련 메서드를 handleEvent 에서 호출해서 사용할 수도 있습니다. 

<button id="elem">클릭해 주세요.</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 = "마우스 버튼을 눌렀습니다.";
    }

    onMouseup() {
      elem.innerHTML += " 그리고 버튼을 뗐습니다.";
    }
  }

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

 

이벤트 핸들러가 명확히 분리되었기 때문에 코드 변경이 원활해졌습니다.

 

참고자료

https://ko.javascript.info/introduction-browser-events#ref-417

https://jaroinside.tistory.com/37

https://ofcourse.kr/js-course/%ED%83%9C%EA%B7%B8%EC%9D%98-on-%EC%86%8D%EC%84%B1