-
[ JavaScript ] JavaScript Event. 이벤트 버블링. 이벤트 위임. 이벤트 막기.PROGRAMMING/JavaScript 2022. 5. 20. 23:34
하루입니다.

이벤트 모델. 그래픽 유저 인터페이스 환경에서 사용자와 상호작용하는 것. 이벤트 소스와, 이벤트와, 이벤트리스너(이벤트핸들러). 우리가 주로 다루는 건 이벤트 발생시 수행 작업이 들어간 함수인 이벤트리스너이다.
이벤트 핸들러의 함수 선호 방식
버튼을 누르면 '안녕' alert가 뜨는 이벤트를 만든다. 원래라면 <button>을 만들고, 실행될 함수를 만들어야 한다. 하지만 이벤트핸들러는 종속성이 강해 타 이벤트에서 사용하기 힘들다. 그렇다면 굳이 함수에 이름까지 붙여가며 만들어야 할까?
<button id="btn-4">버튼4</button> <button id="btn-5">버튼5</button> let btn4 = document.getElementById("btn-4"); btn4.onclick = function() { alert("버튼4이 클릭되었습니다."); } let btn5 = document.getElementById("btn-5"); btn5.addEventListener('click', function() { alert("버튼5이 클릭되었습니다."); });이름 없는 함수를 만들어서 btn 5, btn 5에 대입시켰다.
이벤트 버블링
오늘 나의 질문 : 강사님 혹시 target과 currentTarget의 차이 다시 설명해주실 수 있나요?
대답을 듣다 보니 알게 되었다. 나는 이벤트 버블링 개념 이해를 못했다. 알긴 아는데 글로는 쓰지 못하는 상태.
이벤트 버블링이 무엇이냐. 버블처럼 하위에서 상위로 이벤트가 올라간다는 뜻이다. 자식 엘리먼트에서 부모 엘리먼트로 거슬러 올라가는 것. 자식 엘리먼트에서 발생한 이벤트와 동일한 이벤트에 대한 이벤트 핸들러 함수가 부모 엘리먼트에 등록되어 있는 경우에만 부모 엘리먼트의 이벤트 핸들러 함수가 실행된다. 반대 순서는 캡쳐링이다. 정확히 말하자면 캡쳐링 - 최하위요소 - 버블링 이렇게 돌아간다. 양자택일인데 보통 사람들은 버블링을 선택하는 것. 캡처링을 많이 사용하지 않는 이유는 보통 하위요소를 많이 누를텐데 (div 안의 button, div 안의 ul 안의 li 등) 굳이 상위부터 보고 싶진 않아서가 아닐까?
이벤트 버블링 중단
stopPropagation() : 부모에게 이벤트가 버블링되는 걸 막는다.
stopImmediatePropagation() : 엘리먼트에 같은 이벤트에 대해서 이벤트 핸들러 함수가 여러 개 등록되어 있는 경우, 이벤트 핸들러 함수에서 stopImmediatePropagation()를 실행하면, 다른 이벤트핸들러함수의 실행도 차단한다. 같은 엘리먼트 안에 설정되어 있다면 stop이 설정된 이벤트 외에는 실행이 안 되게 하는 것.
이벤트 버블링의 활용 (이벤트 위임)
- 자식 엘리먼트에서 부모 엘리먼트로 메세지(데이터)를 전달할 수 있다.
- 비슷한 방식으로 여러 엘리먼트를 조작해야 하는 경우, 이벤트 위임을 사용하면 엘리먼트마다 이벤트 핸들러를 바인딩시키지 않고 부모 엘리먼트에 이벤트 핸들러를 딱 하나만 바인딩해서 여러 자식 엘리먼트를 한번에 핸들링 하는 것이다.
- 이게 무슨 소리냐면. 만약 내가 특정 사진을 누르면 그 사진이 크게 보이는 화면을 구현한다고 하자. 그러면 이미지 하나하나 온클릭하면 이 함수가 실행되는데 이 함수 안에는 이런 내용을 구현하고 ... 이렇게 진행해야겠지. 하지만 이벤트 버블링을 사용하면 다음과 같다.
<div> <div id="big-image-box"> <img src="images/poster1.jpg" alt="범죄도시2 포스터"/> </div> <div id="small-image-box" onclick="changeImage(event);"> <img src="images/poster1.jpg" alt="범죄도시2 포스터"> <img src="images/poster2.jpg" alt="쥬라기월드 포스터"> <img src="images/poster3.jpg" alt="그대가 조국 포스터"> <img src="images/poster4.jpg" alt="안녕하세요 포스터"> <img src="images/poster5.jpg" alt="배드 가이즈 포스터"> </div> </div> <script> function changeImage(e) { let imgEl = e.target; // target 안에는 small-image-box의 정보가 들어있다. (이벤트 발생시켰으니까) let imagePath = imgEl.getAttribute("src"); let imageDescription = imgEl.getAttribute("alt"); // 원래 img가 해야 할 것을 div부모 엘리먼트에게 위임한다 let gallaryImgEl = document.querySelector("#big-image-box img"); gallaryImgEl.setAttribute("src", imagePath); gallaryImgEl.setAttribute("alt", imageDescription); }그러니까 ... 이벤트 버블링은 여기서 img - div - div - html 이런 순서로 흐를 것. 내가 div를 누르면(onclick) changeEvent라는 함수가 실행되며 event를 해당 함수에 전달한다(e). changeEvent의 imgEl 함수는 이벤트.target 즉 내가 img를 클릭했을 때의 정보를 전달한다. 그 중 src와 alt를 get해 변수들에 넣는다. 그 후 big-image-box 아이디 내의 img를 찾아 get한 src와 alt를 set해주면 된다. 이제 작은 사진을 누를 때마다 큰 사진은 해당 소스와 대체텍스트로 바뀐다.
이벤트 버블링을 통해 정보가 부모로 가니까, 그 정보를 target 등을 이용해 get set해서 한번에 바인딩하는 법이었다. (휴)
- .target : 실제로 이벤트를 발생시킨 엘리먼트 객체를 제공한다.
- .currentTarget : 현재 실행중인 이벤트 핸들러 함수가 등록된 엘리먼트 객체를 제공한다. 실제로 이벤트를 발생시킨 엘리먼트와 서로 다를 수 있다.
- .type : 발생된 이벤트의 이름을 제공한다.
그래서 타겟과 커런트타겟 차이가 뭐냐. 말 그대로 타겟은 '실제로 이벤트를 발생시킨' 엘리먼트 객체이다. 만약 내가 p - div - html로 이어지는 버블링을 발생시켰다면 여기서 타겟은 p, 커런트타겟도 p이다. 커런트 타겟은 현재 이벤트 핸들러가 '어디서 발생하고 있냐'이다. div에서 이벤트가 발생할 때, 타겟은 p이고 커런트타겟은 div이다.
잘못된 정보에 대한 지적은 언제나 환영입니다.
복습 끝!
'PROGRAMMING > JavaScript' 카테고리의 다른 글
[ JavaScript ] 마우스 이벤트, 키보드 이벤트, 폼 이벤트 (0) 2022.05.23 [ JavaScript ] 브라우저의 이벤트 기본동작 막기 (0) 2022.05.21 [ JavaScript ] 함수 (0) 2022.05.19 [ JavaScript ] 주요 API : 체크상태 변경 / 엘리먼트 조작 / 바로실행함수 (0) 2022.05.19 [ JavaScript ] if문, 주요 API (0) 2022.05.18