Javascript

이벤트 복습하기

이벤트는 브라우저의 윈도우 객체 내에서 발생하는 사건을 말한다. 클릭, 스크롤, 커서의 움직임 등 다양한 이벤트를 감지할 수 있다.

 

특정 객체에서 발생하는 이벤트를 감지하기 위해서는 addEventListener 메서드를 사용하면 된다. 객체에 존재하는 onclick과 같은 이벤트 핸들러 프로퍼티를 사용해도 되지만, addEventListener를 사용하면 하나의 이벤트의 여러 개의 핸들러를 추가할 수 있는 장점이 있다. 게다가 removeEventListener로 핸들러를 제거할 수도 있다.

 

(HTML tag의 어트리뷰트로 핸들러를 등록해줄 수도 있지만, 이 방법은 그다지 권장되지 않는다. HTML 파싱이 먼저 끝난 후에 스크립트가 실행될 수 있도록 자바스크립트 코드를 HTML과 분리시키는 것이 바람직하다.)

 

이벤트 핸들러의 첫번째 파라미터로 이벤트 객체가 자동으로 전달된다. 이벤트 객체의 target 속성을 통해 이벤트가 발생한 요소를 참조할 수 있다.

 

이벤트 핸들러의 this는 이벤트 타깃을 가리킨다. 그러나 개인적으로 핸들러에서 this를 적극 사용하는 것은 좋은 방법이 아닌 것 같다. 만약 핸들러를 화살표 함수로 구현했다면, this는 더 이상 event target을 가리키지 않는다. 화살표 함수는 this 바인딩이 생략되기 때문에 스코프 체인을 따라 가장 가까운 this를 참조하기 때문이다.

 

핸들러에서 이벤트의 기본 동작을 방지하고 싶다면 preventDefault() 메서드를 사용하자. submit 이벤트가 발생했을 때 form의 모든 필드가 채워지지 않았다면, 핸들러 내에서 기본 동작을 방지하고 안내 메세지를 출력해 줄 수 있다.

 

이벤트 버블링은 이벤트가 상위 요소로 전파되는 현상이다. 만약 하위 요소에 클릭 이벤트가 발생하면 핸들러를 실행하고 상위 요소에도 (클릭 이벤트가 등록이 되어 있다면) 이벤트가 발생되어 핸들러가 실행된다. 전파는 최상위 요소까지 전달된다. 기본적으로 모든 이벤트는 버블링이 적용되어 있다.

const divs = document.querySelectorAll('div');

function handleClick(e){ 
  if(e.target.className==="black") console.log('클릭 black!');
  if(e.target.className==="white") console.log('클릭 white!');
  if(e.target.className==="tomato") console.log('클릭 tomato!');
  console.log(e.currentTarget.className);
}

divs.forEach((div)=>{
  div.addEventListener('click', handleClick);
})

각 색상을 한 번씩 클릭해보았다. 이벤트가 가장 바깥쪽 div까지 전파되는 것을 볼 수 있다.

이벤트 캡처링은 이벤트가 하위 요소로 전파되는 현상이다. 상위 요소에서 먼저 이벤트가 발생되고 하위 요소로 탐색해 나가면서 이벤트가 전파된다. 캡쳐링을 위해서는 세번째 인자로 넘겨지는 option 객체의 capture 속성 값을 true로 변경해주어야 한다. 기본 값은 false이다.

 

// ...

div.addEventListner('click', handleClick, {
	capture: true,
});

 

black을 클릭했는데 가장 상위 요소인 tomato에 등록된 이벤트가 먼저 실행된다

 

이벤트 버블링, 캡쳐링이 모두 존재하는 경우엔 캡쳐링 단계가 먼저 실행되고 버블링 단계가 실행된다고 하는데 적절한 예시를 찾지 못했다.

 

이벤트 전파를 막아주기 위해서는 stopPropagation() 메서드를 사용하자.

 

이벤트 버블링이 예상치 못한 결과를 초래하기도 하지만 항상 나쁜 것은 아니다. 이벤트 버블링으로 이벤트 위임을 구현할 수 있다. 만약 각각의 엘리먼트에 이벤트 리스너를 달아줘야 한다면, 꽤나 번거로운 작업이 될 것이다. 게다가 이후에 새롭게 추가되는 엘리먼트가 있다면 이벤트 리스너 또한 새롭게 붙여줘야 한다. 아이템이 많아지면 많아질수록 작업이 매우 힘들어질 것이다. 이런 경우에 상위 요소에만 이벤트 리스너를 등록해주고 하위 요소에서 발생하는 이벤트를 감지하여 핸들러 로직을 수행할 수 있다. 만약 아이템에 따라 다른 처리를 해줘야 한다면 id와 같은 식별할 수 있는 속성을 등록하고, 아이템에 따라 다른 로직을 실행시킬 수도 있다.

 

레퍼런스

 

MDN

캡틴 판교 블로그

 

 

'Javascript' 카테고리의 다른 글

자바스크립트의 메모리 관리  (0) 2022.03.03
map()과 forEach()차이  (0) 2022.01.07
Node.js - Express로 서버 만들기  (0) 2021.12.14
Node.js - http모듈로 서버 만들기  (0) 2021.12.14
Node.js - 모듈/동기/비동기  (0) 2021.12.14