JS 지식_4. Event의 흐름

Derek·2021년 6월 21일
7

JS_knowledge

목록 보기
4/4
post-thumbnail

React 에만 익숙해져 Javascript 의 이벤트 개념을 놓치는 것 같아, 정리해보려고 한다.

크게 3가지를 알아볼 것이다.

  • 이벤트 등록 방법

  • 이벤트 캡쳐링

  • 이벤트 버블링

  • 이벤트 위임


이벤트 등록 방법

사용자가 웹과 상호작용을 할때, 이를 입력으로 받기 위해서 이벤트를 등록합니다.

아래와 같은 방법입니다.

<button>Event</button>

위와 같이 버튼이 하나 존재할때, 아래처럼 버튼에 이벤트를 등록 할 수 있습니다.

let $button = document.querySelector('button');
function onClickBtn(e) {
	console.log(e);
}

$button.addEventListener('click', onClickBtn);

버튼을 눌렀을때, onClickBtn 함수가 실행됩니다.

e 라는 이벤트 객체를 콘솔로 띄우는 함수를 수행하겠네요!

버튼 클릭 -> onClickBtn 함수 실행

이렇게 정리가 되겠습니다.

이처럼 addEventListener() 웹 API는 웹 개발자들이 화면에 동적인 기능을 추가하기 위한 기능입니다.

사용자의 입력에 따라 추가 동작을 구현할 수 있는 방법이죠.

여기서 브라우저는 어떻게 이벤트의 발생을 감지했을까요? 브라우저가 이벤트를 감지하는 방식 2가지를 아래에서 알아보겠습니다.


이벤트 발생 순서

이벤트의 발생순서는 아래와 같습니다.

1. 이벤트 캡쳐링 - 캡처링 단계

2. 타깃 단계

3. 이벤트 버블링 - 버블링 단계

그럼, 1번부터 보도록 합시다.


1. 이벤트 캡처링

이벤트 캡처링은 이벤트가 발생할때 가장 먼저 이루어집니다.

(사실 그렇게 쓰이진 않는답니다.)

이벤트 캡처링은 아래 그림처럼 이루어집니다.

출처: 캡틴판교님

특정 이벤트가 발생했을 때 최상위 요소인 body 태그에서 해당 태그를 찾아 내려갑니다.

즉, 하위요소에 바인딩된 이벤트가 일어나면 그 상단부터 천천히 타고 들어갑니다 :)

얘를 구현하려면 코드는 다음과 같이 구성됩니다.

<body>
	<div class="one">
		<div class="two">
			<div class="three">
              <button class = "btn">Hello World!</button>
			</div>
		</div>
	</div>
</body>

이렇게 생긴 HTML 파일에서,

let $divs = document.querySelectorAll('div');
$divs.forEach(function(div) {
	div.addEventListener('click', logEvent, {
		capture: true // default 값은 false입니다.
	});
});

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

{capture: true} 이라는 구문이 addEventListener 에 추가되면 해당 이벤트를 감지하기 위해 이벤트 버블링과 반대 방향으로 탐색합니다.

사실 이 이벤트 캡처링을 쓸 경우는 많이 없어 보입니다.


2. 이벤트 타겟 단계

간단합니다. 저희가 바인딩한 객체의 이벤트가 발생하는 단계입니다.

아래 사진을 참고해볼게요.

(1). Capture Phase - 이벤트 캡처링이 일어나고,

(2). Target Phase - 타깃에 걸린 이벤트 핸들러가 작동합니다.

(3). 마지막으로 Bubbling Phase - 이제 버블링이 일어납니다.


3. 이벤트 버블링 단계

가장 중요한 이벤트 버블링 단계입니다.

출처: 캡틴판교님

하위의 클릭 이벤트가 상위로 전달됩니다!

아주 간단해요. 코드를 참고해보면,

<body>
	<div class="one">
		<div class="two">
			<div class="three">
              <button class = "btn">Hello World!</button>
			</div>
		</div>
	</div>
</body>

이렇게 생긴 HTML 파일에서,

let $divs = document.querySelectorAll('div');
$divs.forEach(function(div) {
	div.addEventListener('click', logEvent);
});

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

여기서 버튼을 클릭했을때 다음과 같은 결과가 나옵니다 :)

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

따라서, 클래스 명 three -> two -> one 순서로 div 태그에 등록된 이벤트들이 실행됩니다. 마찬가지로 two 클래스를 갖는 두 번째 태그를 클릭했다면 two -> one 순으로 클릭 이벤트가 동작합니다.

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

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


이벤트 위임

그럼 이 이벤트 동작들을 어디다 쓸것이냐, 바로 이벤트 위임에 쓰입니다.

이벤트 위임이란,

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

이라고 볼 수 있겠습니다. 코드로 보면 더 쉬울것 같아요.

<h1>오늘의 할 일</h1>
<ul class="itemList">
	<li>
		<input type="checkbox" id="item1">
		<label for="item1">이벤트 버블링 학습</label>
	</li>
	<li>
		<input type="checkbox" id="item2">
		<label for="item2">이벤트 캡쳐 학습</label>
	</li>
</ul>

이렇게 생긴 간단한 TodoList 는 다음과 같이 작동합니다.

let $inputs = document.querySelectorAll('input');
$inputs.forEach(function(input) {
	input.addEventListener('click', function(event) {
		alert('clicked');
	});
});

하지만 여기서 todo 가 사용자가 인풋을 넣음에 따라 늘어난다면,

그 새로생긴 친구들은 해당 이벤트가 바인딩 되지 않습니다.

$inputs 는 이미 컴파일 된 상태에서 todo 가 추가된거니까요.

그럴땐 부모에게 이벤트를 할당하세요.

let $itemList = document.querySelector('.itemList');
$itemList.addEventListener('click', function(event) {
	alert('clicked');
});

위와 같이요.

즉, 다시 HTML 파일을 참고해보면 ul 태그에, 이벤트를 위임해 준것이죠.

<h1>오늘의 할 일</h1>
<ul class="itemList"> << 여기에 이벤트를 바인딩!!!!!!!!!!!!
	<li>
		<input type="checkbox" id="item1">
		<label for="item1">이벤트 버블링 학습</label>
	</li>
	<li>
		<input type="checkbox" id="item2">
		<label for="item2">이벤트 캡쳐 학습</label>
	</li>
</ul>

이렇게 부모에게 이벤트를 위임하면, 새로 생길 Todo 들에게도 이벤트가 자동적으로 바인딩 된답니다. :)


빠르게 이벤트 개념에 대해서 정리해보았습니다!

잘못된 내용이 있다면 댓글로 알려주세요 :)

profile
Whereof one cannot speak, thereof one must be silent.

0개의 댓글