이안의 평일코딩

40장 이벤트 본문

Study/JS Diver

40장 이벤트

이안92 2021. 8. 19. 21:27
반응형

p.754

- 함수를 언제 호출할 지 알 수 없으므로 개발자가 명시적으로 함수를 호출하는 것이 아니라 브라우저에게 함수 호출을 위임하는 것이다.

 

p.758

- 이벤트 핸들러(event handler, event listener)는 이벤트가 발생했을 때 브라우저에 호출을 위임한 함수다. 다시 말해, 이벤트가 발생하면 브라우저에 의해 호출될 함수가 이벤트 핸들러다.

 

> 이벤트 핸들러를 등록하는 3가지 방법

1. 어트리뷰트 방식

- 이벤트 핸들러 어트리뷰트의 이름은 onclick과 같이 on 접두사와 이벤트의 종류를 나타내는 이벤트 타입으로 이루어져 있다. DOM 노드의 이벤트 핸들러 프로퍼티에 함수 참조를 할당하는 프로퍼티 방식과는 달리 함수 호출문 등의 문을 할당한다.

<!DOCTYPE html>
<html>
<body>
  <button onclick="sayHi('Lee')">Click me!</button>
  <script>
    function sayHi(name) {
      console.log(`Hi! ${name}.`);
    }
  </script>
</body>
</html>

2. 프로퍼티 방식

- 이벤트 핸들러를 등록하기 위해 이벤트를 발생시킬 객체인 이벤트 타깃($button)과 이벤트의 종류를 나타내는 문자열인 이벤트 타입(onclick) 그리고 이벤트 핸들러(function)를 지정해야 한다. 어트리뷰트 방식의 HTML과 자바스크립트가 뒤섞이는 문제를 해결할 수 있지만 이벤트 핸들러 프로퍼티에 하나의 이벤트 핸들러만 바인딩할 수 있다는 단점이 있다.

<!DOCTYPE html>
<html>
<body>
  <button>Click me!</button>
  <script>
    const $button = document.querySelector('button');
    
    // 이벤트 핸들러 프로퍼티에 이벤트 핸들러를 바인딩
    $button.onclick = function () {
      console.log('button click');
    };
  </script>
</body>
</html>

 

3. addEventListner 메서드 방식

- 프로퍼티 방식과는 달리 이벤트 타입에 on 접두사를 붙이지 않는다. 마지막 매개변수에는 이벤트를 캐치할 이벤트 전파 단계를 지정하는데 생략하거나 false를 지정하면 버블링 단계에서 이벤트를 캐치하고, true를 지정하면 캡처링 단계에서 이벤트를 캐치한다.

<!DOCTYPE html>
<html>
<body>
  <button>Click me!</button>
  <script>
    const $button = document.querySelector('button');
    
    // addEventListener 메서드 방식
    $button.addEventListener('click', function() {
      console.log('button click');
    });
  </script>
</body>
</html>

- addEventListener 메서드로 등록한 이벤트 핸들러를 제거하려면 EventTarget.prototype.removeEventListener 메서드를 사용한다. 이벤트 핸들러 프로퍼티는 null을 할당하여 이벤트 핸들러를 제거할 수 있다.

 

p. 779

> 이벤트 전파

- 생성된 이벤트 객체는 이벤트를 발생시킨 DOM 요소인 이벤트 타깃을 중심으로 DOM 트리를 통해 전파된다. 이벤트 전파는 이벤트 객체가 전파되는 방향에 따라 3단계로 구분할 수 있다.

 

- 캡처링 단계: 이벤트가 상위 요소에서 하위 요소 방향으로 전파

- 타깃 단계: 이벤트가 이벤트 타깃에 도달

- 버블링 단계: 이벤트가 하위 요소에서 상위 요소 방향으로 전파

 

 

p. 785

- 이벤트 위임(event delegation)은 여러 개의 하위 DOM 요소에 각각 이벤트 핸들러를 등록하는 대신 하나의 상위 DOM 요소에 이벤트 핸들러를 등록하는 방법을 말한다. 

<body>
  <nav>
    <ul id="fruits">
      <li id="apple" class="active">Apple</li>
      <li id="banana">Banana</li>
      <li id="orange">Orange</li>
    </ul>
  </nav>
  <script>
    const $fruits = document.getElementById('fruits');
    ...
    // 모든 내비게이션 아이템(li 요소)에 이벤트 핸들러를 등록한다.
    document.getElementById('apple').onclick = activate;
    document.getElementById('banana').onclick = activate;
    document.getElementById('orange').onclick = activate;
   
    // 이벤트 위임: 상위 요소(ul#fruits)는 하위 요소의 이벤트를 캐치할 수 있다.
    $fruits.onclick = activate;
  </sciprt>
</body>

- 이때 이벤트 객체의 currentTarget 프로퍼티는 언제나 변함없이 $fruits 요소를 가리키지만 이벤트 객체의 target 프로퍼티는 실제로 이벤트를 발생시킨 DOM 요소를 가리킨다.

 

p. 787

- 이벤트 객체의 preventDefault 메서드는 DOM 요소의 기본 동작을 중단시키고, 이벤트 객체의 stopPropagation 메서드는 이벤트 전파를 중지시킨다.

 

p.796

- 생성된 커스텀 이벤트 객체는 버블링되지 않으며 preventDefault 메서드로 취소할 수도 없다. 즉, 커스텀 이벤트 객체는 bubbles와 cancelable 프로퍼티의 값이 false로 기본 설정된다.

 

p.799

- 기존 이벤트 타입이 아닌 임의의 이벤트 타입을 지정하여 커스텀 이벤트 객체를 생성한 경우 반드시 addEventListener 메서드 방식으로 이벤트 핸들러를 등록해야 한다. 이벤트 핸들러 어트리뷰트/프로퍼티 방식을 사용할 수 없는 이유는 'on + 이벤트 타입'으로 이루어진 이벤트 핸들러 어트리뷰트/프로퍼티가 요소 노드에 존재하지 않기 때문이다.

 

반응형
Comments