티스토리 뷰

Javascript

:자식 element가 여럿있을때 event 전파 막는 효과적인 방법


| Why?


> 상황: 


모바일 웹에서, Modal의 overlay 영역의 scroll방지하기 위해 overlay 영역을 touch 햇을때 touchEvent 리스너에 모달을 닫는 function을 넣어, 모달을 닫게 하는 기능을 구현해야 하는 상황이 생겼었습니다. 


> 어려움이 있었던점:


모달의 overlay 영역은 부모 영역에 생기고 그 하위에 모달 컴포넌트의 자식 요소들이 있는 상황이였는데요,

이때자식 element에는 onClick 이벤트로 새로운 모달을 띄우는 이벤트가 걸려있는 상황이였습니다.


따라서, 

  • 기존의 모달안의 자식 요소들에 걸려있는 클릭시 새로운 모달창이 뜨는 onClick event
  • 부모 (모달 overlay 영역)에게 걸려있는 화면 touch시 모달창이 꺼지는 touch event
이벤트 전파로 자식 요소를 클릭했을때 위와 같은 두 이벤트가 동시에 실행되는 상황을 막아서, (react 모달의 overlay 영역부모 엘리먼트 터치시에만 모달 창이 닫히는 이벤트를 발생시켜야 하는 상황이였습니다. 


그렇지 않으면 이벤트 전파로 인해, 유저는 자식 엘리먼트를 클릭해 새로운 창을 뜨는 상황을 기대했지만, 자식을 클릭했더라도 부모 이벤트에 걸려있는 touch시 모달 창이 닫히는 이벤트가 발생해서, 모달 창이 닫혀버려 원하는 상황을 구현할 수 없었습니다.


그 이유는 모두 아시다시피, event는 dom tree 내에서 캡쳐링- 버블링의 과정을 거치기 때문에, 부모 element에만 touch 와 관련한 이벤트를 걸어 놓았더라도, 이벤트 전파가 되어 자식 엘리먼트에 이벤트가 발생해도 부모의 event 역시 실행되기 때문입니다.


요약:  부모 요소 안에 있는 여러 자식 요소들의 클릭으로 인한 이벤트 전파를 막아야 하는 상황


| HOW TO SOLVE

부모의 이벤트 영역 touch시에만, 발생시켜야해서, e.target이 e.cuurentTarget과 같을시에만 실행하도록

if (e.target !== e.currentTarget) return; 과 같이 부모 node touch시에만 touch 이벤트가 실행되도록 하여, 자식 node 클릭 시 이벤트 전파로 인해 모달이 꺼지는 경우를 방지 하는 방식으로 코드를 작성하여 문제를 해결했습니다.


물론, 많이들 사용하는 e.stopPropagtion 을 활용하여, 자식 엘리먼트에서 전파를 막아도 되지만, 부모 엘리먼트 단에서 if (e.target !== e.currentTarget) return; 과 같은 코드로 막을 수 있으면, 각각의 자식요소들에서 e.stopPropagtion 로 처리를 해줄 필요가 없어, 자식요소들에서 중복된 여러 코드들을 사용하지 않아도 됩니다.

  • e.stopPropagtion 의 예제



위 예는 stopPropogation 메소드로 이벤트 전파를 막는 간단한 예제였고,


아래는 문제 해결 상황에서 if (e.target !== e.currentTarget) return;를 활용해 부모쪽에만 코드를 추가하여, 자식 엘리먼트들의 이벤트 전파를 막은 코드입니다.


handleTouch = e => {
// 부모 touch 시에만 동작하도록 하기 위한 부분입니다.
if (e.target !== e.currentTarget) return;
  this.closeSearchForm();
};

handleTouchEnd = e => {
// 부모 touch 시에만 동작하도록 하기 위한 부분입니다.
if (e.target !== e.currentTarget) return;
  e.preventDefault();
  this.closeSearchForm();
};

handleOverlayTouch = () => {
const el = document.querySelector('.ReactModal__Overlay');
  el.addEventListener('touchstart', this.handleTouch);
  el.addEventListener('touchend', this.handleTouchEnd);
};

...

# 모달 컴포넌트
<Modal
 onAfterOpen={this.handleOverlayTouch}
 isOpen={isSearchFormOpen}
 onClose={this.closeSearchForm}
 position={modalPositionEnum.top}
>

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
TAG
more
«   2024/04   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
글 보관함