[ 프로그래머스 - 프론트엔드 개발을 위한 자바스크립트 온라인 스터디 ] 2주차 정리

aeong98·2022년 6월 23일
0
post-thumbnail

2주차 스터디

💡 이벤트 위임 기법을 사용해 이벤트를 효과적으로 처리하고 커스텀 이벤트를 사용하는 방법을 익혔다.

✅ 2주차 요구사항


2주차에서는 1주차에서 구현했던 todoApp을 기반으로, todolist 의 추가 및 삭제가 가능하도록 구현하는 미션을 받았다.

이때, 1주차때 만들었던 함수를 다른 파일로 분리해, 컴포넌트처럼 동작하도록 만드는게 키 포인트였다.

  • todo를 입력하는 Input 부분 컴포넌트화
  • 완료된 Todo 개수를 표시하는 부분 컴포넌트화
  • 이벤트 처리(Event delegate, 커스텀 이벤트)
  • localStorage 를 사용해, 새로고침후에도 이전 데이터를 보여줄 수 있도록 하기

등의 보너스 요구사항도 구현했다. 컴포넌트 끼리의 상태와, 이벤트가 서로 얽혀있는데 이런 컴포넌트 간의 상태를 어떻게 통합적으로 유지하고, 전달하는지에서 많은 고민을 했던 것 같다.

특히 이벤트 처리(Event delegate, 커스텀 이벤트) 는 처음 사용해보는 기법이었어서, mdn 을 보며 예제 코드를 많이 참고했다.

👩‍💻 관련 개념 정리


1️⃣ addEventListener

이벤트 리스너는 DOM 객체에서 이벤트가 발생할 경우, 해당 이벤트 처리 핸들러를 추가할 수 있는 오브젝트이다. 이벤트 리스너를 이용하면 특정 DOM 에 위에 말한 Javscript 이벤트가 발생할 때 특정 함수를 호출한다.

특정 DOM 요소에 이벤트 리스너를 등록할 때는 addEventListener를 사용한다.

addEventListener(type, listener);
addEventListener(type, listener, options);

type
수신할 이벤트 유형을 나타내는 대소문자 구분 문자열입니다.

listener
지정한 이벤트(Event 인터페이스를 구현한 객체)를 수신할 객체로, 이벤트 발생시 호출할 콜백함수를 넘긴다.

options
이벤트 수신기의 특징을 지정할 수 있는 객체입니다.

2️⃣ 이벤트 버블링, 이벤트 캡처, 이벤트 위임

이벤트 버블링 (Event Bubbling), 이벤트 캡쳐(Event Capturing)

이벤트 버블링은 특정 화면 요소에서 이벤트가 발생했을 때, 해당 이벤트가 더 상위 화면 요소들로 전달되어 가는 특성을 의미한다.

<body>
	<div class="one">
		<div class="two">
			<div class="three">
			</div>
		</div>
	</div>
</body>
var divs = document.querySelectorAll('div');
divs.forEach(function(div) {
	div.addEventListener('click', logEvent);
});

function logEvent(event) {
	console.log(event.currentTarget.className);
}

// 최하위 div 태그를 클릭했을 떄?
// three
// two
// one

div 태그 한개만 클릭했는데, 3개의 이벤트가 발생하는 이유는. 브라우저가 이벤트를 감지하는 방식 때문이다.

브라우저는 특정 화면 요소에서 이벤트가 발생했을 때 그 이벤트를 최상위에 있는 화면 요소까지 이벤트를 전파한다.

여기서 주의해야 할 점은 각 태그마다 이벤트가 등록되어 있기 때문에 상위 요소로 이벤트가 전달되는 것을 확인할 수 있다. 만약 이벤트가 특정 div 태그에만 달려 있다면 위와 같은 동작 결과는 확인할 수 없다..

이와 같은 하위에서 상위 요소로 이벤트가 전파 되는 방식을 이벤트 버블링(Event Bubbling)이라고 한다.

이와 반대로, 상위 요소에서 하위로 이벤트가 전파되는 방식은 이벤트 캡처링(Event Capturing) 이라고 한다.

event.stopPropagation()

위와 같은 상황에서 이벤트가 전파되는 것을 막기 위해, **stopPropagation()** 이라는 웹 API를 사용할 수 있다.

// 이벤트 버블링 예제
divs.forEach(function(div) {
	div.addEventListener('click', logEvent);
});

function logEvent(event) {
	event.stopPropagation();
	console.log(event.currentTarget.className); // three
}

// 이벤트 캡쳐 예제
divs.forEach(function(div) {
	div.addEventListener('click', logEvent, {
		capture: true // default 값은 false입니다.
	});
});

function logEvent(event) {
	event.stopPropagation();
	console.log(event.currentTarget.className); // one
}

위 API는 해당 이벤트가 전파되는 것을 막는다. 따라서, 이벤트 버블링의 경우에는 클릭한 요소의 이벤트만 발생시키고 상위 요소로 이벤트를 전달하는 것을 방해한다.

이벤트 위임(Event Delegation)

이벤트 위임은 실제 바닐라 JS로 웹 앱을 구현할 때 자주 사용하게 되는 코딩 패턴이다.

‘하위 요소에 각각 이벤트를 붙이지 않고 상위 요소에서 하위 요소의 이벤트들을 제어하는 방식’이다.

이벤트 위임을 사용하면 요소마다 핸들러를 할당하지 않고, 요소의 공통 조상에 이벤트 핸들러를 단 하나만 할당해도 여러 요소를 한꺼번에 다룰 수 있다.

<ul id="menu">
  <li><button id="file">파일</button></li>
  <li><button id="edit">편집</button></li>
  <li><button id="view">보기</button></li>
</ul>

/ ** 방법1 **/

document.getElementById("file").addEventListener("click", function(e) {
  // 파일 메뉴 동작
});
document.getElementById("edit").addEventListener("click", function(e) {
  // 편집 메뉴 동작
});
document.getElementById("view").addEventListener("click", function(e) {
  // 보기 메뉴 동작
});

// 메뉴가 추가될 때마다 이벤트 핸들러가 하나씩 늘어난다.
// 이벤트 위임을 사용하면 상위 엘리먼트인 <div id="menu> 에만 이벤트 리스너를 추가하면 된다.

document.getElementById("menu").addEventListener("click", function(e) {
  var target = e.target;
  if (target.id === "file") {
    // 파일 메뉴 동작
  } else if (target.id === "edit") {
    // 편집 메뉴 동작
  } else if (target.id === "view") {
    // 보기 메뉴 동작
  }
});

3️⃣ 커스텀 이벤트 사용하기

자바스크립트에서는 내장 이벤트를 할당할 수 있을 뿐만 아니라, 이벤트를 직접 만들 수 도 있다.

Event 생성자

내장 이벤트의 클래스는 DOM 요소 클래스같이 계층 구조를 형성한다. 내장 이벤트 클래스 계층의 꼭대기에는 Event 클래스가 있고, Event 객체는 다음과 같이 생성할 수 있다.

let event = new Event(type[, options]);
  • name : 이벤트 이름
  • options
    • babbles : true 이면 이벤트 버블링됨.
    • cancelabel : true 이면, event.preventDefault() 가 동작함.

dispatchEvent

이벤트 객체를 생성한 다음엔 elem.dispatchEvent(event) 를 호출해, 요소에 있는 이벤트를 실행시켜줘야 한다.

예를 들면 다음과 같다.

<h1 id="elem">Hello from the script!</h1>

<script>
  // 버블링이 일어나면서 document에서 이벤트가 처리됨
  document.addEventListener("hello", function(event) { // (1)
    alert("Hello from " + event.target.tagName); // Hello from H1
  });

  // 이벤트(hello)를 만들고 elem에서 이벤트 디스패치
  let event = new Event("hello", {bubbles: true}); // (2)
  elem.dispatchEvent(event);

  // document에 할당된 핸들러가 동작하고 메시지가 얼럿창에 출력됩니다.

</script>

마무리


이번 2주차 미션에서는, 위의 이벤트 처리 기법 중 이벤트 위임 (Event Delegation) 을 사용해서 todoList 중 요소 한개를 클릭했을 때, 취소선이 생기도록 동작하는 이벤트를 추가했다.

또한, removeAll 이라는 커스텀 이벤트를 만들어, 최상위 컴포넌트인 App 에서 해당 이벤트를 받아, 하뒤 컴포넌트에서 해당 이벤트가 수신되면 todoList의 모든 데이터를 삭제하는 기능을 구현했다.

이벤트 버블링, 캡처링의 개념에 대해 이해하고, 이벤트 위임, 커스텀 이벤트를 사용해, 각 컴포넌트들간의 복잡한 이벤트를 효율적으로 처리하는 방법을 익혔던 시간이었다.

참고


profile
프린이탈출하자

0개의 댓글