[javascript] 브라우저 이벤트 소개

sangyong park·2023년 2월 20일
0
post-thumbnail

브라우저 이벤트 소개

이벤트는(event)는 무언가 일어났다는 신호이다. 모든 DOM 노드는 이런 신호를 만들어 낸다. 참고로, 이벤트는 DOM에만 한정되진 않는다.

자주 사용되는 유용한 DOM 이벤트

마우스 이벤트:

  • click // 요소 위에서 마우스 오른쪽 버튼을 눌렀을 때 발생한다.
  • contextmenu // 요소 위에서 마우스 오른쪽 버튼을 눌렀을 때 발생한다.
  • mouseover와 mouseout // 마우스 커스를 요소 위로 움직였을 때, 커서가 요소 밖으로 움직였을 때 발생한다.
  • mousedown과 mouseup // 요소 위에서 마우스 왼쪽 버튼을 누르고 있을 때, 마우스 버튼을 뗄 때 발생한다.
  • mousemove // 마우스를 움직일 때 발생한다.

폼 요소 이벤트:

  • submit // 사용자가 form을 제출할 때 발생한다.
  • focus // 사용자가 input과 같은 요소에 포커스 할 때 발생한다.

키보드 이벤트:

  • keydown과 keyup // 사용자가 키보드 버튼을 누르거나 뗄 때 발생한다.

문서 이벤트:

  • DOMContentLoaded // HTML이 전부 로드 및 처리되어 DOM 생성이 완료되었을 때 발생한다.

css 이벤트:

  • transitionend // CSS 애니메이션이 종료되었을 때 발생한다.

이벤트 핸들러

이벤트에 반응하려면 이벤트가 발생했을 때 실행되는 함수인 핸들러를 할당해야 한다.

핸들러는 사용자의 행동에 어떻게 반응할지를 자바스크립트 코드로 표현한 것입니다.

핸들러는 여러 가지 방법으로 할당할 수 있다.

HTML 속성

HTML 안의 on<event> 속성에 핸들러를 할당할 수 있다.

아래 같이 input 태그의 onclick 속성에 click 핸들러를 할당하는 것과 같다.

<input value="클릭해 주세요" onclick="alert('클릭!') type="button">

버튼을 클릭하면 onclick 안의 코드가 실행된다.

여기서 주의해야 할 것은 속성값 내에서 사요된 따옴표이다. 속성값 전체가 큰따옴표로 둘러싸여 있기 때문에 작은 따옴표로 둘러쌓는다.클릭!")"과 같이 속성값 내부에 또 큰따옴표를 쓰면 코드가 작동하지 않는다.

긴 코드를 HTML 속성값으로 사용하는 것은 추천하지 않는다. 만약 코드가 길다면, 아래와 같이 함수를 만들어서 이를 호출하는 방법을 추천한다.

<script>
  function countRabbits() {
    for(let i=1; i<=3; i++) {
      alert(`토끼 ${i}마리`);
    }
  }
</script>

<input type="button" onclick="countRabbits()" value="토끼를 세봅시다!">

DOM 프로퍼티

DOM 프로퍼티 on<event>을 사용해도 핸들러를 할당할 수 있다.

<input id="elem" type="button" value="클릭해 주세요.">
<script>
  elem.onclick = function() {
    alert('감사합니다.');
  };
</script>

핸들러를 HTML 속성을 사용해 할당하면, 브라우저는 속성값을 이용해 새로운 함수를 만든다. 그리고 생성된 함수를 DOM 프로퍼티에 할당한다.

따라서 DOM 프로퍼티를 사용해 핸들러를 만든 위 예시는 HTML 속성을 사용해 만든 바로 위쪽 예시와 동일하게 작동한다.

onclick 프로퍼티는 단 하나밖에 없기 때문에, 복수의 이벤트 핸들러를 할당할 수 없다.

아래 예시와 같이 핸들러를 하나 더 추가하면, 기존 핸들러는 덮어씌워진다.

<input type="button" id="elem" onclick="alert('이전')" value="클릭해 주세요.">
<script>
  elem.onclick = function() { // 기존에 작성된 핸들러를 덮어씀
    alert('이후'); // 이 경고창만 보입니다.
  };
</script>

핸들러를 제거하고 싶으면 elem.onclick = null 같이 null을 할당하면 된다.

this로 요소에 접근하기

핸들러 내부에 쓰인 this의 값은 핸들러가 할당된 요소이다.

아래 예시의 this.innerHTML에서 this는 button 이므로 버튼을 클릭하면 버튼 안의 컨텐츠가 얼럿창에 출력된다.

<button onclick="alert(this.innerHTML)">클릭해 주세요.</button>

자주 하는 실수

이벤트를 다룰 때는 아래 주의사항을 항상 염두에 둬야한다.

이미 존재하는 함수를 직접 핸들러에 할당하는 예시를 살펴보자

<script>
function sayThanks() {
  alert('감사합니다!');
}

elem.onclick = sayThanks;
</script>

이때 함수는 sayThanks처럼 할당해야 한다. sayThanks()를 할당하면 동작하지 않는다.

<script>
// 올바른 방법
button.onclick = sayThanks;

// 틀린 방법
button.onclick = sayThanks();
</script>

sayThanks() 같이 괄호를 덧붙이는 것은 함수를 호출하겠다는 것을 의미한다. 위 예시의 마지막 줄처럼 sayThanks()를 프로퍼티에 할당하면 함수 호출의 결과값이 할당된다.

함수 sayThanks가 아무것도 반환하지 않는다면 onclick 프로퍼티엔 undefined가 할당되므로 이벤트가 원하는 대로 동작하지 않는다.

그런데, HTML 속성값에는 괄호가 있어야 한다.

<input type="button" id="button" onclick="sayThanks()">

브라우저는 속성값을 읽고, 속성값을 함수 본문으로 하는 핸들러 함수를 만들기 때문에 이런 차이가 발생한다.

브라우저는 onclick 프로퍼티에 새로운 함수를 할당한다.

addEventListener

HTML 속성과 DOM 프로퍼티를 이용한 이벤트 핸들러 할당 방식엔 근본적인 문제가 있다. 하나의 이벤트에 복수의 핸들러를 할당할 수 없다는 문제이다.

버튼을 클릭하면 버튼을 강조하면서 메시지를 보여주고 싶다고 해 보자

그럼 두 개의 이벤트 핸들러가 필요하다. 하지만 기존 방법으로는 프로퍼티가 덮어씌워 진다는 문제가 있다.

<script>
input.onclick = function() { alert(1); }
// ...
input.onclick = function() { alert(2); } // 이전 핸들러를 덮어씀
</script>

이럴 때 사용할 수 있는게 addEventListener와 removeEventListener이다.

<script>
element.addEventListener(event, handler, [options]);
</script>

event
이벤트 이름(예: "click")

handler
핸들러 함수

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

  • once: true이면 이벤트가 트리거 될 때 리스너가 자동으로 삭제된다.
  • capture: 어느 단계에서 이벤트를 다뤄야 하는지를 알려주는 프로퍼티로, 호환성 유지를 위해 options를 객체가 아니 false/true로 할당하는 것도 가능한데 이는 {capture: false/true} 와 동일하다.
  • passive: true이면 리스너에서 지정한 함수가 preventDefault()를 호출하지 않는다.

핸들러 삭제는 removeEventListener로 한다.

삭제는 동일한 함수만 할 수 있다.

<script>
element.removeEventListener(event, handler, [options]);
</script>
profile
Dreams don't run away It is always myself who runs away.

0개의 댓글