프로젝트를 진행하면서 문제 해결을 하기 위해 찾아보다가 stopPropagation() 개념을 처음 접했다.
e.preventDefault() 는 몇번 써봤는데 비슷한 결(?)인 것 같고, 차이점을 확실히 알고 싶어서 모던 JS 책에서 찾아보게 되었다.
해당 개념을 찾아보게 된 상황
- 부모 컴포넌트는 기록된 식단 아이템 컴포넌트로서, 클릭하면 해당 식단 아이템의 상세페이지로 이동하는 onClick 이벤트 핸들러 함수가 지정되어 있음
- 자식 컴포넌트는 휴지통 그림 버튼이고, 해당 버튼을 눌렀을 때 팝업을 띄우는 컴포넌트임
- 문제는 휴지통을 클릭했을 때 팝업창이 뜨지 않고 상세페이지로 이동해버리는 것
- 현재 상황에서는 휴지통 버튼 역시 컨테이너에 속하므로 클릭했을 때 상세페이지로 이동하게 되는 것이다.
해결방법
⇒ 팝업 컴포넌트와 삭제 버튼 모두에 e.stopPropagation() 을 추가한다.
- 안트디자인의 PopConfirm 을 사용하는데 여기에는 onClick 속성이 없고 대신에 onPopupClick 이라는 속성이 있어서 그 이벤트 핸들러 함수로 추가해주었다.
- 삭제 버튼은 onClick에 추가해주었다.
<Container onClick={() => linkToDetailPage(idx)}>
...
<Popconfirm
...
onPopupClick={(e) => e.stopPropagation()}
>
<DeleteTwoTone
onClick={(e) => {
e.stopPropagation();
handleOpenChange(idx);
}}
/>
</Popconfirm>
...
</Container>
모던 자바스크립트 Deep Dive 를 읽고 작성한 학습용 게시글입니다.
DOM 요소의 기본 동작 중단
- DOM 요소는 저마다 기본 동작이 있다.
- 예를 들어, a 요소를 클릭하면 href 어트리뷰트에 지정된 링크로 이동하고,
- checkbox 요소 또는 radio 요소를 클릭하면 체크 또는 해제된다.
- form에 submit 이벤트가 감지되면 form의 값들이 초기화된다.
- 이벤트 객체의
preventDefault
메서드는 이러한 DOM 요소의 기본 동작을 중단시킨다.
<!DOCTYPE html>
<html lang="en">
<body>
<a href="www.google.com">go google</a>
<input type="checkbox" />
<form>
<input type="text" />
<button type="submit">버튼</button>
</form>
</body>
<script>
document.querySelector("a").onclick = (e) => {
// a 요소의 기본 동작을 중단한다.
e.preventDefault();
};
document.querySelector("input[type=checkbox]").onclick = (e) => {
// input 요소의 기본 동작을 중단한다.
e.preventDefault();
};
document.querySelector("form").addEventListener("submit", (e) => {
// submit 액션의 기본 동작을 중단한다.
e.preventDefault();
});
</script>
</html>
- 위와 같이 e.preventDefault()를 추가해주면,
- a 태그는 클릭해도 지정된 링크로 넘어가지 않고,
- checkbox input 은 체크가 되지 않고,
- form이 submit 되어도 form 내부의 input 태그의 값이 초기화 되지 않는다.
이벤트 전파 방지
- 이벤트 객체의
stopPropagation
메서드는 이벤트 전파를 중단시킨다.
<!DOCTYPE html>
<html lang="en">
<body>
<div class="container">
<button class="button1">Button1</button>
<button class="button2">Button2</button>
<button class="button3">Button3</button>
</div>
<script>
// 이벤트 위임. 클릭된 하위 버튼 요소의 color를 변경한다.
document.querySelector(".container").onclick = ({ target }) => {
if (!target.matches(".container > button")) return;
target.style.color = "red";
};
// .button2 요소는 이벤트를 전파하지 않으므로 상위 요소에서 이벤트를 캐치할 수 없다.
document.querySelector(".button2").onclick = (e) => {
e.stopPropagation(); // 이벤트 전파 중단
e.target.style.color = "blue";
};
</script>
</body>
</html>
- 위 예제를 살펴보면 상위 DOM 요소인 container 요소에 이벤트를 위임했다.
- 따라서 하위 DOM 요소에서 발생한 클릭 이벤트를 상위 DOM 요소인 container 요소가 캐치하여 이벤트를 처리한다.
- 이때 btn2 요소는 자신이 발생시킨 이벤트가 전파되는 것을 중단하여 자신에게 바인딩된 이벤트 핸들러만 실행되도록 한다.
- 이처럼
stopPropagation
메서드는 하위 DOM 요소의 이벤트를 개별적으로 처리하기 위해 이벤트의 전파를 중단시킨다.
'BOOK > 모던 자바스크립트 Deep Dive' 카테고리의 다른 글
[ 모던 자바스크립트 Deep Dive ] 22. this (2) | 2024.01.13 |
---|---|
[ 모던 자바스크립트 Deep Dive ] 24장 클로저 (1) | 2024.01.11 |
[ 모던 자바스크립트 Deep Dive ] 15장 let, const 키워드와 블록 레벨 스코프 (0) | 2024.01.02 |
[ 모던 자바스크립트 Deep Dive ] 23장 실행 컨텍스트 (1) | 2023.12.28 |
[ 모던 자바스크립트 Deep Dive ] 14장 전역 변수의 문제점 (1) | 2023.12.26 |