본문 바로가기

JavaScript

JavaScript - 이벤트 핸들링

이벤트 핸들러 등록 방법

  1. dom요소에 접근 후, onclick 프로퍼티를 준다.
  2. html태그에 onclick속성을 준다.
  3. addEventListener를 통해 이벤트를 등록한다.

1. dom요소에 접근 후, onclick 프로퍼티를 준다.

const btn = document.querySelector('.login-btn');
btn.onclick = function(){
	console.log("login");
}
  • 이 경우, 기존 onclick프로퍼티에 있던 값을 덮어쓴다.
  • 기존값을 그대로 두고 추가만 하는 방법은 3번이고, 아래와 같다.(가장 권장되는 방법임!)

3. addEventListener를 통해 이벤트를 등록한다.

function login(){
	console.log("login");
}
btn.addEventListener('click', login); // 클릭 이벤트 등록
btn.removeEventListener('click', login); // 클릭 이벤트 삭제

 

  • removeEventListener 를 할 때에는 addEventListener를 할 때 썼던 참조값을 똑같이 써야 삭제된다.
function login(){
	console.log("login");
}
btn.addEventListener('click', login);
btn.removeEventListener('click', login); // 삭제된다.


btn.addEventListener('click',function(){console.log("Hi")});
btn.removeEventListener('click',function(){console.log("Hi")}); // 삭제되지 않는다.

 

  • 이벤트를 전달할 때에는 함수 명만을 전달해야한다.
btn.addEventListener('click', login); // 정상동작
btn.addEventListener('click', login()); // login함수는 return값이 없으므로 undefined가 넘겨진다.

이벤트 객체

이벤트 핸들러가 되는 함수의 첫번째 파라미터는 무조건 이벤트 객체이다.

모든 이벤트객체들은 타입과 상관없이 아래의 프로퍼티를 공통적으로 가진다.

  • type : 이벤트 이름. click, mouseup, keydown 등.
  • target : 이벤트가 발생한 요소.
  • currentTarget : 이벤트 핸들러가 등록된 요소
  • timeStamp : 이벤트 발생 시각(페이지가 로드된 이후부터 경과한 밀리초)
  • bubbles : 버블링 단계인지를 판단하는 값

이벤트 버블링

  • 한 요소에서 이벤트가 발생할 경우, 같은 타입의 이벤트에 한해서 부모의 이벤트, 부모의 부모이벤트.... window객체까지 이벤트를 실행한다.
  • 현재요소 이벤트 실행 > 부모요소 이벤트 실행 > 부모의 부모요소 이벤트 실행 >.....> window객체를 만날때 까지 모든 이벤트를 순서대로 실행한다.
  • target은 이벤트가 실행된 지점을 나타내기때문에 현재요소에서도, 부모요소에서도 같은 값을 출력한다.
  • currentTarget은 이벤트사 실행된 요소를 출력하기때문에 현재요소에서는 현재요소를, 부모요소에서는 부모요소를 출력한다.

버블링 멈추기

element.stopPropagation();

 

 

  • 버블링을 막으면 타겟요소의 이벤트만 발생하고, 부모요소의 이벤트들은 발생하지 않는다.
  • 하지만 권장되지 않는다.
  • 왜냐면 상위요소에 등록되어있는 이벤트가 버블링이 막힌 내부요소의 범위만큼 동작하지 못하게 되기 때문이다.

이벤트 캡처링

자주 쓰이진 않는다.

먼저 표준 dom이벤트에서 정의한 이벤트 흐름의 3단계는 다음과 같다.

  1. 캡처링 단계 : 이벤트가 하위 요소로 전파되는 단계
  2. 타깃 단계 : 이벤트가 실제 타깃 요소에 전달되는 단계
  3. 버블링 단계 : 이벤트가 상위 요소로 전파되는 단계

 

  • 캡처링 단계에서 이벤트를 발생시키고 싶다면, addEventListner를 할 때에 세번째 파라미터로 "true" 또는 "{capture:true}" 를 전달하면 된다.
element.addEventListener('click', login, true);
// 또는
element.addEventListener('click', login, {capture: true});

이벤트 위임

  • 자식요소에서 발생하는 이벤트를 부모요소에서 다루는 것을 이벤트 위임이라고 한다.
  • 자식요소의 이벤트를 부모요소에 위임했다고 보면 된다.
  • 이벤트 위임은 버블링을 이용한 것이기 때문에 자식요소에서 버블링을 (stopPropagation을 통해) 막아놓는다면 이벤트가 발생하지않는다.
// html 부분
<body>
	<ul id="list">
    	<li class="item">밥먹기</li>
        <li class="item">운동하기</li>
        <li class="item">청소하기</li>
    </ul>
</body>


// javaScript 부분
const list = document.querySelector('#list');
list.addEventListener('click', function(e){
	e.target.classList.toggle('done');
});

const li = document.createElement('li');
li.classList.add('item');
li.textContent = '일기 쓰기';
list.append(li);
  • 위와같은 코드에서, 각각의 li들을 클릭했을 때 이벤트를 발생시키고 싶은 것인데, "list" 라는 부모요소에 이벤트 핸들러를 등록시켰다.
  • 원래라면 li들에 for문을 통해 이벤트를 등록시켰을텐데 그러지 않았다는 뜻임.
  • 그런데 위와같이 작성할 경우, list에 포함되지만 li에는 포함되지 않는 여백을 클릭한 경우에도 이벤트가 발생한다.

따라서 아래와같이 수정한다.

const list = document.querySelector('#list');
list.addEventListener('click', function(e){
	// 아래의 if문을 추가했다.
	if(e.target.calssList.contains('item')){
    	e.target.classList.toggle('done');
    }
});

const li = document.createElement('li');
li.classList.add('item');
li.textContent = '일기 쓰기';
list.append(li);
  • 타겟의 classList에 "item"이 포함되어있는지 확인 후, 작업하도록 추가했다.
  • 추가적으로, e.target.tagName은 태그를 대문자로 가지고있다고 한다.

브라우저의 기본 이벤트 동작

  • a태그는 href속성의 값으로 이동하는 기본 동작을 한다.
  • input태그는 포커스가 가능하고, 포커스된 채로 키보드를 누를경우 값이 입력되는 기본동작을 한다.
  • 이러한 기본동작을 막는 방법은 다음과 같다.
aLink.addEventListener('click', function(e){
	e.preventDefault();
    alert('지금은 이동할 수 없습니다.');
})
  • preventDefault사용이 권장되지는 않는다. 꼭 필요한 부분에만 사용해야한다.

마우스 버튼 이벤트

mouseEvent의 타입 몇가지

  • mousemove : 마우스 포인터가 이동할 때
  • mouseover : 마우스 포인터가 요소 밖에서 안으로 이동할 때
  • mouseout : 마우스 포인터가 요소 안에서 밖으로 이동할 때
  • mouseenter : 마우스 포인터가 요소 밖에서 안으로 이동할 때(버블링 발생X)
  • mouseleave : 마우스 포인터가 요소 안에서 밖으로 이동할 때(버블링 발생X)

자식요소까지 영향을 끼치게 하고 싶은 경우에는 mouseover/mouseout을 사용하고,

자식요소에는 영향을 끼치지 않고 해당요소에서만 이벤트 핸들러를 다루고자 한다면 mouseenter/mouseleave 를 사용하면 되겠다.

mouseEvent의 property 몇 가지

  • mouseEvent.clientX, clientY : 화면에 표시되는 창을 기준으로 마우스 포인터의 위치를 알 수 있다(마우스를 고정한채 위아래 스크롤을 할 경우, 같은 값을 출력한다.)
  • mouseEvent.pageX, pageY : 웹문서 전체를 기준으로 마우스 포인터의 위치를 알 수 있다.(마우스를 고정한채 스크롤을 해도 다른 값을 얻는다.)
  • mouseEvent.offsetX, offsetY : 이벤트가 발생한 요소(e.target)를 기준으로 마우스 포인터의 위치를 알 수 있다.
  • mouseEvent.relatedTarget : 이벤트가 발생하기 직전(또는 직후)에 마우스가 위치해 있던 요소를 출력한다.

키보드이벤트

키보드 이벤트의 타입 몇가지

  • keydown : 키보드를 누르는 순간 이벤트가 발생. (권장된다.)
  • keypress : 키보드를 누르는 순간 이벤트가 발생하지만 출력값에 변화를 일으키는 키에만 이벤트가 발생한다.(esc나 control 등에는 반응 없고 키 하나를 꾹 누르고 있어도 이벤트는 한번만 인식한다. 또한 영어가 아니면 인식하지 못하는 등의 문제가 있기 때문에 웹 표준에서는 권장하지 않는다.)
  • keyup : 키보드를 눌렀다가 뗀 순간 이벤트가 발생.

키보드 이벤트의 property 몇 가지

  • keyboardEvent.key : 이벤트가 발생할 때 누른 키보드 값
  • keyboardEvent.code : 이벤트가 발생할 때 누른 키의 키보드에서 물리적인 위치

 

input태그의 이벤트 타입 몇가지

  • focusin : 포커스 되었을 때 이벤트가 발생
  • focusout : 포커스가 빠져나갈 때 이벤트가 발생
  • focus :  포커스 되었을 때 이벤트가 발생(버블링X)
  • blur :  포커스가 빠져나갈 때 이벤트가 발생(버블링X)
  • input : 사용자가 입력을 할 때 이벤트가 발생(처음 입력한 경우만을 의미)
  • change : 요소의 값이 변했을 때 이벤트가 발생(처음 값과 입력이 끝난 후의 값이 변했을 때에만 발생)
  • input에 포커스를 시켜놓고 엔터를 누르면, 입력이 끝났다는 것을 의미하기때문에 포커스를 잃지 않고 change이벤트를 발생시킬 수 있다.

scroll이벤트

  • 보통 window객체에 scroll이벤트를 설정한다.
  • window객체의 property를 활용해 사용할 수도 있는데 아래와 같이 사용가능하다.
let lastScrollY = 0;

function onSroll() {
  const nav = document.querySelector('#nav');
  const toTop = document.querySelector('#to-top');
  const STANDARD = 30;
  
  if (window.scrollY > STANDARD) { // 스크롤이 30px을 넘었을 때
    nav.classList.add('shadow');
    toTop.classList.add('show');
  } else { // 스크롤이 30px을 넘지 않을 때
    nav.classList.remove('shadow');
    toTop.classList.remove('show');
  } 

	if (window.scrollY > lastScrollY) { // 스크롤 방향이 아랫쪽 일 때
    nav.classList.add('lift-up');
  } else { // 스크롤 방향이 윗쪽 일 때
    nav.classList.remove('lift-up');
  }

  lastScrollY = window.scrollY;
}

window.addEventListener('scroll', onSroll);
  • 스크롤이 30px을 넘었을 때와 넘지 않았을 때를 구분할 수 있고
  • 스크롤이 아래방향을 향하고 있는지, 윗 방향을 향하고 있는지 구분할 수 있다.

 

 

 

 

'JavaScript' 카테고리의 다른 글

JavaScript - HTTP 메소드  (0) 2023.10.07
JavaScript - this  (1) 2023.10.07
JavaScript - 노드 선택  (0) 2023.10.03
JavaScript - 변수, 자료형 등 기본 문법  (1) 2023.10.02
JavaScript - 브라우저의 동작 원리  (0) 2023.10.01