캡쳐링,버블링,이벤트 위임

2024. 5. 10. 16:56카테고리 없음

HTML은 부모와 자식관계를 가지고 있음
=> 여러개의 태그들이 서로 중첩되어 사용된다.

이 부분에 대해 어떻게 교통정리가 될것인지를 본다

버튼을 클릭했을때 버튼을 감싸고있는 부모 엘리먼트들이 있는데,
제일 먼저 HTML에 장착되어있는 이벤트 핸들러가 호출이 되고
바디에 장착되어있는 핸들러 , 필드셋, 마지막으로 클릭한 버튼에 장착된 핸들러가 순서대로 호출이 된다면
이것은 "캡처링"이라고 합니다. (Capturing) 

그리고, 우리가 클릭한 깊숙한 엘리먼트에서 이벤트가 발생을 하고, 그 위에 있는 상위 이벤트가 발생하고
상위 이벤트로의 방향대로 이벤트가 발생하는 (호출되는) 것을 "버블링" (Bubbling)이라고 합니다.
웹 브라우저의 이벤트 모델은 부모에 장착되어 있는 이벤트 부터 자식으로 나아가는 캡쳐링을 지원하고
자식에서 먼저 이벤트 핸들러가 호출이 되고 부모 이벤트 핸들러로 나아가는 "버블링"도 지원한다. 

[캡처링]
어떤 태그로 보이는지 분석
HTML 태그의 테두리 붉은색 ,그다음 안쪽 body 태그는 녹색 테두리,

필드셋 태그는 파란색 테두리,안쪽 버튼은 검은색 테두리를 가지고 있음
HTML의 구조와 그 구조에 따른 각각의 태그들 (엘리먼트)들이 어떻게 보이는지 파악

id 값이 target인 element => 버튼의 addeventlistner를 통해 클릭이 일어났을때 

=> 함수 핸들러가 실행되도록 이벤트를 설정해놓음
버튼 클릭 되었을때, 핸들러에 해당하는 함수가 실행

함수 내부에는 phases 배열이 정의
해당 배열에는 캡쳐링,타겟,버블링 이라고 하는 3개의 문자열이 저장
첫번째 인자는 신경 X, 두번째 인자는 현재 클릭이 일어나서 해당 이벤트가 호출된 이벤트 타겟

=> 위의 값을 의미 (인풋이라는 값을 갖게됨)

인풋 => 현재 해당 이벤트 핸들러가 호출된 이벤트 타겟

코드내에서 두번째 라인을 실행시키면 필드셋 (인풋 태그를 감싸고 있는 필드셋)

addeventlistner로 클릭핸들러를 준것

2줄 출력 => 핸들러 함수 2번 호출
첫번째는 필드셋 출력 두번째는 인풋 출력

필드셋은 인풋을 감싸고 있고,이벤트가 설치가 되고,

인풋태그에도 이벤트가 설치가 된 상태에서 사용자가 인풋태그를 클릭했다면

먼저 필드셋이 호출이되고, 그다음에 인풋에 설치되어있는 이벤트가 설치가 된다는것을 추정 가능
실행결과를 본다면 첫번째는 필드셋 두번째는 인풋이 실행결과로 출력

코드내에서 console.log => this.node 로그는 현재 해당 이벤트 핸들러가 this.nodeName의 값은 
현재 실행되고 있는 이벤트 핸들러가 어떤 엘리먼트의 소속인지를 알려주는 정보

그래서 필드셋이라고 하는 정보가 포함되어있는것은 필드셋에 설치되어있는 이벤트 핸들러가 호출됐을때 출력된 내용
인풋이라고 적혀져 있는것은 인풋태그에 있는 이벤트 핸들러가 호출됐을때 실행이 된것이라고 할 수 있다.
event.target.nodename 이라고 하는것은 맥락에서는 언제나 인풋 태그를 가리킨다 라는 것을 알 수 있다.

사용자가 target을 클릭했다면 클릭한 지점을 둘러싸고 있는 여러 계층들이 존재하지만 그 중에서 가장 깊숙한 곳에 있고
가장 구체적인 대상이라고 할 수 있는 것이 이벤트 타겟에 해당된다라는 것이다..
이벤트 타겟 노드네임은 여러개의 이벤트 핸들러를 중첩되어 있는 태그들에 설치했다 하더라도
event.target에 저장되어 있는 값은 언제나 가장 깊은 곳에 있는 엘리먼트가 된다는 것이고
this.nodename 을 통해 (this를 통해) 접근 하는 것은 이벤트 핸들러가 호출된 엘리먼트를 의미하게 된다.

제일 바깥쪽에는 HTML태그에 설치되어 있는 이벤트 핸들러가 호출된 결과가 출력이 되니까
HTML에 설치된 이벤트 핸들러가 가장 먼저 실행이 됨을 알수 있다..
그다음에 BODY에 설치된 핸들러가 실행이 되고
그다음에는 FIELDSET에 설치된 핸들러 마지막으로 INPUT태그에 설치된 핸들러가 호출된다.

 

그래서 각각의 엘리먼트들(4줄)에다가 각각 관계가 있음
해당 상태에서 target을 클릭하게 되면 호출된 내용을 통해 알수 있는 부분은 
HTML, BODY, FIELDSET,INPUT 순으로 출력이 되었기 떄문에 (가장 바깥쪽에 있는 핸들러부터 안쪽에 붙어 있는 핸들러 순서)대로 호출이 되고 있다. 바깥쪽에서 안쪽으로 (부모에서 자식으로) 호출되는 방식을 캡쳐링이라고 합니다.
캡쳐링을 사용하는 경우는 매우 드문 편이다. 자체는 사용을 안하지만 이벤트가 전달하는 흐름을 설명하는데 유효하다.

캡쳐링과 버블링은 비슷하지만 정 반대의 방향성을 가지고 있다.
실제로 자주 사용되는건 버블링 (이벤트 전파 "실세")
true값을 false로 일괄적으로 변경을 하고 실행을 하게 된다면

INPUT FIELDSET BODY HTML 이전에 봤던 것과 정 반대되는 방향성을 가지고 실행이 된 것을 볼수 있다.
다시 말해 안쪽에서 바깥쪽으로 실행되고 있다는 것(버블링)
마치 거품이 커지는 것과 비슷하다는 의미 (버블링)
차이 => addeventListener 3번째 인자를 변경했을 뿐
3번째 인자 => 캡쳐링 (use capturing)

이벤트 핸들러가 캡쳐링 방식으로 작동하길 원한다면 3번째 인자로 true값으로
버블링으로 동작하게 하고싶다면 false로 값을 하거나 비워두면 된다.
body 이벤트에 이벤트를 설치하면서 캡쳐링을 사용하겠다는 뜻에서 3번째 인자를 true로 줬다면

target버튼을 클릭하면 해당 부분을 감싸고 있는 body를 클릭한 것과도 같기 때문에 
body에 설치되있는 eventListner가 호출이 되고 그다음 target에 설치된 EventListener가 호출이 됨
만약 캡쳐링을 하지 않겠다고 지정했다면 target 엘리먼트에서 이벤트 핸들러가 호출이 되고
바깥쪽 body 엘리먼트에 설치되어있는 이벤트 핸들러가 호출이 된다. 

이벤트를 전파한다는것 
이벤트가 중첩적으로 장착될 수 있기 때문에 해당 경우에 어떤 순서로 이벤트 핸들러를 호출할 것인지(실행할 것인지)에 대한 규약이 이벤트 전파라고 하는 것


phases라고 정의해놓은 배열 event, eventPhase라는것을 사용했고
eventPhase 프로퍼티는 현재 이벤트 핸들러가 호출이 될때 호출된 것이 캡쳐링 와중에서 호출된것이라면
eventPhase는 1이라는 값을 가지게 됨
버블링 와중에 호출된 것이라면 3이라는 값을 가지게 됨
이벤트 핸들러가 가장 깊숙한 곳에 있는 엘리먼트 (가장 말단에 있는 자식 엘리먼트에 설치되어있는 핸들러라고 한다면)
eventPhase 값은 1을 가지게 됨 
Phases 라고 되어있는 배열에 적혀있는 값들을 현재 핸들러가 호출되는 모드가 무엇인지 알아내기 위해 코드를 작성한 것


이벤트가 바깥 => 안 // 안=> 바깥 와중에 body태그에 설치되어있는 이벤트핸들러까지만 호출하고
바깥쪽 엘리먼트는 이벤트 전파가 되지 않도록 하는 방법은 
EventstopPropagation 이라고 하는것
이벤트 핸들러를 하나 더 만들고 스탑 핸들러라는 이름을 가지고 있고
event.StopProPagation 추가가 된 상태
body 엘리먼트에 설치되어 있는 이벤트 리스너를 스탑 핸들러로 바꿈
나머지는 핸들러를 호출하게 되는데 바디에 설치되있는 이벤트 핸들러는 스탑 핸들러이고,
스탑 핸들러가 호출이 될때 제일 마지막 행에서 event.stopPropagaion 메서드(이벤트 객체가 가지고 있는)가 호출
Propagation => 전파라는 뜻 
즉 이벤트 전파를 스탑한다는 뜻을 가지고 있다.

 

버튼을 클릭하면 
INPUT , FIELDSET, BODY 가 나왔지만 HTML은 나오지 않았다..
전파가 HTML까지는 가지 않고, BODY 이벤트 핸들러를 호출하는 것을 마지막으로 해서 끊겼다.
그것이 가능한 이유는 바디에 설치된 이벤트 핸들러가 호출이 될때, 이벤트 객체가 가지고 있는 메서드 중에서 
스탑 프로파게이션 이라는 메서드를 호출했기 때문에 저것을 호출하면 자바스크립트는
그 이후에 등장하는 이벤트 핸들러에 대한 호출을 끊어버린다. => STOP PROPAGATION