본문 바로가기
프로젝트

마우스 포인터가 요소를 벗어나지 않았음에도 onMouseOut 이벤트가 실행되는 이유 + 해결방법

by 1two13 2023. 3. 26.
728x90
반응형

이전에 노션에 정리를 해둔 내용이나, 제대로 정리되지 않은 부분이 있어 블로깅을 하게 되었다. 그리고 노션은 나만 보기도 하니깐!

 

문제상황


나는 아이콘에 mouse를 hover했을 때 dropdown 메뉴가 화면에 노출되고, 메뉴 안에 있는 값을 클릭했을 때 해당 값이 선택되도록 구현하고 싶었다.

 

dropdown 메뉴를 구현하기 위해 <div>에게 onMouseOver 이벤트와 onMouseOut 이벤트를 등록한 상황이다. 

 

근데 여기서 확인되는 첫 번째 문제점이 있었다.

선택된 영역 위에, 즉 div 위에 마우스를 올렸을 때 onMouseOver 이벤트만 발생되어야 하는데, onMouseOut 이벤트도 발생되는 문제점이 있었다.

참고로 onMouseOut 이벤트는 마우스의 커서가 해당 요소에서 위치하다가 빠져나갈 때 일어나는 이벤트이고, onMouseOver 이벤트는 마우스의 커서가 해당 요소 위에 위치할 때 일어나는 이벤트이다. 

 

간단하게 코드로 보자면 아래와 같다. 

<div
  onMouseOver={() => {
    console.log('mouseOver');
    setIsHover(true);
  }}
  onMouseOut={(e: any) => {
    console.log('Mouse out the element');
    setIsHover(false);
  }}
  className="border-2"
>
  <Icons icon={faUser} onClick={moveToMyPage} />
  {isHover && <IsHover />}
</div>;

코드 결과

까만색 border는 div 영역이고, 초록색 border는 Icons 컴포넌트 영역이다. 

console.log 출력 화면

초록색 border 안에서만 마우스를 이동했을 때, onMouseOver 이벤트만 실행되어야 한다. 하지만 Mouse out the element도 출력되는 것을 확인할 수 있다. (초록색 border를 안을 제외한 까만색 border 안쪽에서 마우스를 이동했을 때는 onMouseOver 이벤트만 실행된다.) 

728x90

 

 

해결 과정


일반적으로 onMouseOver 이벤트는 마우스 포인터가 요소 위로 이동할 때 발생하고, onMouseOut 이벤트는 마우스 포인터가 요소를 벗어날 때 발생한다. 

 

그러나, onMouseOver 이벤트가 발생하는 영역이 다른 영역을 포함하고 있는 경우, 마우스 포인터가 이벤트 대상 요소를 벗어나 다른 영역 위로 이동할 때 onMouseOut 이벤트가 발생할 수 있다. 

 

위의 코드로 설명하자면 div 요소에 onMouseOver 이벤트와 onMouseOut 이벤트를 설정하고, 이 요소가 Icons 컴포넌트를 포함하고 있는 경우, 마우스 포인터가 Icons 컴포넌트 위로 이동할 때 onMouseOut 이벤트가 발생할 수 있는 것이다. 

 

이를 방지하려면, onMouseOut 이벤트 핸들러에서 이벤트 대상 요소가 이벤트가 발생한 요소의 자식 요소인지 확인하여, 자식 요소 위로 마우스 포인터가 이동한 경우 이벤트를 무시하도록 처리해주면 된다. 

<div
  onMouseOver={() => {
    console.log('mouseOver');
    setIsHover(true);
  }}
  onMouseOut={(e) => {
    if (!e.currentTarget.contains(e.relatedTarget)) {
      console.log('Mouse out the element');
      setIsHover(false);
    }
  }}
  className="border-2"
>
  <Icons icon={faUser} onClick={moveToMyPage} />
  {isHover && <IsHover />}
</div>;

onMouseOut 이벤트 핸들러에서 contains() 메서드를 사용하여, 이벤트 대상 요소가 이벤트가 발생한 요소의 자식 요소인지를 확인했다. 이를 통해, 자식 요소 위로 마우스 포인터가 이동한 경우에만 이벤트를 무시할 수 있도록 처리해줬다.

 

그럼 아까와 똑같은 상황으로 실험을 했을 때 아래와 콘솔 출력 결과를 확인할 수 있다.

console.log 출력 화면

반응형

 

 


질문이나 잘못된 점은 댓글로 남겨주세요 :)💖

728x90
반응형

댓글