티스토리 뷰

이벤트객체★ ★ ★ ★ ★

이벤트객체는 이벤트 핸들러 안에 포함된 객체로 이벤트가 발생하면 생성된다. 

event객체에는 이벤트와 관련된 다양한 정보를 가지고 있다.

이벤트의 종류에 따라 이벤트 객체의 property와 method들을 골라서 사용할 수 있다.

예를 들어 이벤트가 발생된 대상(태그)에 접근할 때 this라는 키워드를 사용할 수 있다. 

 

[이벤트 객체의 property]

- altKey : 이벤트가 발생했을 때 alt가 눌렸는지에 대한 여부를 boolean 값으로 반환한다.

- ctrlKey : 이벤트가 발생했을 때 ctrl이 눌렸는지에 대한 여부를 boolean 값으로 반환한다.

- shiftKey : 이벤트가 발생했을 때 shift가 눌렸는지에 대한 여부를 boolean 값으로 반환한다.

- button : 마우스에서 눌린 키의 값을 반환한다.

 (왼쪽 버튼을 눌렀으면 0을 반환, 휠을 누르면 1 반환, 오른쪽 버튼을 눌렀으면 2를 반환) 

- charCode : keypress이벤트가 발생했을 때 어떤 키를 눌렀는지 유니코드 값으로 키의 정보를 반환한다.

- clientX, clientY : 이벤트가 발생한 요소의 x좌표 위치와 y좌표 위치를 반환한다.

- pageX, pageY : 현재 문서를 기준으로 이벤트가 발생한 X좌표 위치와 Y좌표 위치를 반환한다.

- screenX, screenY : 현재 화면을 기준으로 이벤트가 발생한 X좌표 위치와 Y좌표 위치를 반환한다.

- target★ : 이벤트가 최초로 발생한 대상을 반환한다.

- timeStamp : 이벤트가 발생한 시간을 반환한다. 

- type : 발생한 이벤트 종류의 이름을 반환한다.

- which : 키보드와 관련된 이벤트가 발생했을 때 키의 유니코드 값을 반환한다. 

 

[메서드]

- preventDefault(); 기본 이벤트(태그 안에 기본적으로 들어있는 기능 ex. a태그-링크이동, button태그-제출)를 취소할 때 사용한다.  

- stopPropergation(); 기본 이벤트를 취소할 때 사용한다. 이번트의 버블링을 막는다. 

 

[이벤트 객체 기본형]

요소.on이벤트명 = function(e 또는 event){ <-매개변수 event 안에 이벤트 객체가 할당된다.

   let 변수 = event.프로퍼티명;  <- 이벤트 객체의 현재 값을 변수에 할당 

   event.프로퍼티명 = 값; <- 이벤트 객체의 현재 값을 다른 값으로 바꾸기 

   event.메서드명(); <- 이벤트 객체의 메서드 실행 
}

<img src="./img/image02.jpg" alt="풍경" id="image" />

    <script>
      const image = document.querySelector('#image');

      //이벤트 핸들러의 매개변수 안에는 이벤트 객체가 들어있다.
      //변수 이름은 상관 없지만 통상적으로 e 또는 event로 많이 짓는다.
      image.onclick = function (event) {
        //this : image(이벤트가 발생한 이미지 태그요소)
        alert('클릭한 이미지 파일? : ' + this.src);

        let positionX = event.clientX;
        let positionY = event.clientY;

        console.log('클릭이벤트가 발생한 X좌표 위치는 ', positionX);
        console.log('클릭이벤트가 발생한 Y좌표 위치는 ', positionY);
      };
    </script>

addEventListener()메서드

앞에서 배운 이벤트 핸들러는 한 요소당 하나씩밖에 연결할 수 없었다.

하지만 만약 하나의 태그 요소에 여러 이벤트를 추가하고 싶다면 addEventListener()메서드를 이용할 수 있다.

예를 들어 검색창에 돋보기 버튼을 누르거나 enter를 눌러도 동일한 검색 기능 이벤트가 실행되어야한다면 이럴 때 addEventListener() 메서드를 사용한다. 

 

[기본형]

요소.addEventListener("이벤트명",function(){ 이벤트 핸들러 }, 캡쳐 여부 );

 

-이벤트명 : 요소에 추가할 이벤트 유형을 지정. 단 click이나 keydown처럼 on이라는 키워드 없이 이벤트명만 쓴다. 

-이벤트 핸들러 : 이벤트가 발생하면 실행시킬 코드를 넣는다. 함수를 정의할 때 매개변수자리에는 event객체를 참조할 수 있다. 

-캡쳐 여부 : 이벤트를 캡쳐할지 여부를 지정하며 기본값은 false이고 true나 false값을 지정할 수 있다. 

기본값이 false이기 때문에 기본값 쓰고 싶으면 false생략 가능. true면 캡쳐링, flase면 버블링을 하겠다는 의미이다.

이벤트 캡쳐링은 DOM의 부모 노드에서 자식 노드로 이벤트를 전달하는 것이고 버블링은 DOM의 자식노드에서 부모노드로 이벤트를 전달하는 것을 말한다. 만약 버블링할 경우 이 자리는 생략할 수 있다. 

<img src="./img/image01.jpg" alt="풍경1" id="cover1" />
    <img src="./img/image02.jpg" alt="풍경2" id="cover2" />

    <script>
      const cover1 = document.querySelector('#cover1');
      const cover2 = document.querySelector('#cover2');

      //일반 함수에 addEventListener연결하기
      cover1.addEventListener('mouseover', changePic); //일반함수 호출시 이벤트에서는 ()를 붙이지 않는다!
      cover1.addEventListener('mouseout', originPic);

      //마우스가 올라갔을때 실행할 이벤트 핸들러
      function changePic() {
        cover1.src = './img/image02.jpg';
      }

      //마우스가 벗어났을때 실행할 이벤트 핸들러
      function originPic() {
        cover1.src = './img/image01.jpg';
      }

      //익명함수로 addEventListener연결하기
      cover2.addEventListener('mouseover', function () {
        cover2.src = './img/image01.jpg';
      });
      cover2.addEventListener('mouseout', function () {
        cover2.src = './img/image02.jpg';
      });
    </script>

버블링과 캡쳐링

버블링이랑 DOM의 자식노드에서 부모노드로 이벤트를 전달하는 것을 말하며 이벤트에 기본값으로 내장된 기능이다. 단, 모든 이벤트가 전부 버블링되는 것은 아니다.(포커스 이벤트는 버블링이 없음)

캡쳐링은 반대로 부모노드에서 자식노드로 이벤트를 전달하는 것을 말하며 기본값은 false로 캡쳐링이 되지 않고 

addEventListener의 마지막 인자값 자리에 true를 넣었을 경우에만 발생한다.

버블링

버블링의 원리는 간단하다. 

한 요소에 이벤트가 발생하면 이 요소에 할당된 이벤트 핸들러가 동작하고 이어서 부모요소의 핸들러가 동작한다.

가장 최상위에 있는 조상 요소를 만날 때까지 이 과정이 반복되면서 요소 각각에 할당된 핸들러가 동작한다.

event.target★

부모요소의 핸들러는 이벤트가 정확히 어디서 발생했는지에 대한 정보를 얻을 수 있다.

이벤트가 발생한 가장 안쪽 요소는 target요소라고 부르고 event.target 프로퍼티를 이용하여 접근할 수 있다. 

 

event.target은 this(=event.currentTarget)와 이러한 차이점이 있다.

1. event.target은 실제 이벤트가 시작된 '타겟'요소를 말한다.

    버블링이 진행되더라도 바뀌지 않는다.

2. this는 '현재 요소'로 현재 실행 중인 핸들러가 할당된 요소를 가리킨다.

버블링 중단하기 

이벤트 버블링은 타깃 이벤트에서 시작하여 html요소를 거쳐 document 객체를 만날 때까지 각 노드에서 모두 발생한다. 몇몇 이벤트는 window객체까지 거슬러 올라가기도 한다. 이 때 모든 이벤트핸들러가 실행된다. 

그런데 만약 핸들러에게 이벤트를 완전히 처리한 후 버블링을 중단하도록 명령하고 싶다면 event.stopPropergation() 메서드를 사용하면 된다.

캡처링

이벤트에는 버블링 현상 외에도 캡처링(capturing)이라는 흐름이 존재한다. 

실제 코드에서는 자주 쓰이지는 않지만 종종 유용하게 쓰일 때도 있다.

 

표준 DOM이벤트 흐름에는 3단계가 있다.

1. 캡쳐링 단계 - 이벤트가 하위요소로 전파되는 단계 

2. 타겟 단계 - 이벤트가 실제 타겟 요소에 전파되는 단계 

3. 버블링단계 - 이벤트가 상위 요소로 전파되는 단계 

 

[기본형]

요소.addEventListener("이벤트명",이벤트핸들러,{capture : true});

요소.addEventListener("이벤트명",이벤트핸들러,{true}); ★

<!--  span을 클릭했지만 div에 있는 alert이 실행됨 : 버블링 -->
    <div onclick="alert('div에 할당된 이벤트 핸들러!')" class="first_div">
      <span>span태그를 클릭해도 div에 할당된 이벤트가 동작합니다~!</span>
    </div>

    <!-- 버블링 확인하기 -->
    <form onclick="alert('form')">
      form
      <div onclick="alert('div')">
        div
        <p onclick="alert('p')">p</p>
      </div>
    </form>

    <!-- 버블링 막기 -->
    <div onclick="alert('버블링은 여기까지 도달할 수 없습니다.')">
      <button type="button" onclick="event.stopPropagation()">
        클릭해주세요
      </button>
    </div>
  </body>

 

버블링&캡처링 실습 

 <title>버블링&캡처링 실습</title>
    <style>
      body * {
        margin: 10px;
        padding: 0;
        border: 1px solid dodgerblue;
        text-align: center;
      }
    </style>
  </head>
  <body>
    <form>
      form
      <div>
        div
        <p>p</p>
      </div>
    </form>

    <!-- js -->
    <script>
      for (let elem of document.querySelectorAll('*')) {
        //캡쳐링
        elem.addEventListener(
          'click',
          (e) => alert(`캡처링 : ${elem.tagName}`),
          true
        );

        //버블링
        elem.addEventListener('click', (e) =>
          alert(`버블링 : ${elem.tagName}`)
        );
      }
    </script>

 

<title>버블링&캡쳐링2</title>
    <style>
      * {
        margin: 0;
        padding: 0;
      }
      form {
        background-color: seagreen;
        width: 200px;
        height: 200px;
        text-align: center;
        color: #fff;
        margin-top: 40px;
        display: flex;
        justify-content: center;
        align-items: center;
      }
      div {
        width: 120px;
        height: 120px;
        background-color: sandybrown;
        display: flex;
        flex-direction: column;
        justify-content: center;
        align-items: center;
      }
      p {
        width: 50px;
        height: 50px;
        background-color: slateblue;
      }
    </style>
  </head>
  <body>
    <h4>태그를 클릭하면 event.target과 this의 정보를 볼 수 있습니다.</h4>

    <form id="form">
      <div>
        DIV
        <p>P</p>
      </div>
    </form>

    <script>
      const formTag = document.getElementById('form');

      formTag.onclick = function (event) {
        //내가 클릭한 요소(event.target)의 배경색을 바꿈
        event.target.style.backgroundColor = 'tomato';

        console.log(event);

        setTimeout(() => {
          alert('target : ' + event.target.tagName + ', this:' + this.tagName);
          //css 배경색을 원래대로 변경한다. 이때 빈문자로 표시할 수 있다.
          event.target.style.backgroundColor = '';
        }, 0);
      };
    </script>