마우스 이벤트 정복

차유림·2021년 12월 3일
10

마우스 이벤트 정복

mouseenter vs mouseover

mouse 이벤트에 요소에 마우스를 올라갔을때와 벗어났을 때만 있으면
이 글을 작성하지 않았을 것이다.

마우스 올라갔을 때 : mouseover / mouseenter
마우스 벗어날 때 : mouseout / mouseleave

각각 두가지 씩 있는것이다.. 이게 참 헷갈린다.
어떤 차이가 있을까?

한마디로 요약하면 이벤트 버블링이 발생하느냐 안하느냐의 차이다.

콘솔출력

mouseenter/mouseleave 를 먼저 보자.
이 이벤트는 버블링이 발생하지 않는다.
즉, 자식 요소에 mouse가 올라가고 벗어나도
해당 요소에는 아무영향을 주지 않는다.
따라서 아래에서 직접 테스트해보면
자식에 마우스를 올리고 내림과 상관없이
해당 요소를 들어가고 나갈 때에만 이벤트가 발생하기 때문에
콘솔에도 mouseenter - mouseleave 가 한번만 출력된다.

반대로 mouseover/mouseout 같은 경우에는
이벤트 버블링이 발생한다.
자식요소에 mouseover 가 발생하면
부모요소에서 mouseover 이벤트 핸들러가 동작하는 것이다.
따라서 처음 진입시 div - mouseover 발생하고
자식요소에 진입하면 div - mouseout, p - mouseover 가 발생한다.
(여기서 e.target 에 베이지 배경 스타일을 주었기 때문에
부모의 배경색이 없어지게 된다)
다시 자식 -> 부모요소로 마우스 이동하면
p - mouseout, div - mouseover 가 발생하고
마지막으로 부모요소에서 마우스가 나가면 div - mouseout 이벤트가 발생한다.

hover 는 mouseenter/mouseleave 와 같이 동작한다.
짝맞춰 알고있으면 편한데, 글자수가 긴 enter/leave가 한 쌍
상대적으로 짧은 over/out이 버블링 일어나는 한 쌍으로 기억하면 좋을 것 같다ㅎㅎ

리액트 SyntheticEvent

리액트에서 이벤트 핸들러 사용시, 전달되는 이벤트 객체는
nativeEvent 를 래핑한 syntheticEvent 이다.
syntheticEvent는 nativeEvent와 동일한 인터페이스를 가지고 있지만
모든 브라우저에서 동일하게 동작하도록 래핑된 것이라고 한다.

여기서 syntheticEvent는 nativeEvent와 직접 대응되지는 않는다!
공식문서에서는 예시로 onMouseLeave의 event.nativeEvent가 mouseout임을 들었다.
직접 확인해보자.
이벤트 핸들러에 전달되는 syntheticEvent 객체를 콘솔에 출력해보면
nativeEvent 정보를 확인해볼 수 있다.

+) 추가로 리액트 공부할 때, input에 onChange를 사용하면
입력할때마다 값이 변경되는 것이
네이티브이벤트 input처럼 동작하는 것인지 궁금했었는데
이것도 확인해보았다.

function App() {
  return (
    <div className='App'>
      <input
        type='text'
    	onMouseLeave={(e) => console.log(e.nativeEvent.type)}
        onInput={(e) => console.log('input', e.nativeEvent)}
        onChange={(e) => console.log('change', e.nativeEvent)}
      />
    </div>
  );
}

input에 마우스를 올렸다가 떼고 값도 입력해보면,
onMouseLeave의 nativeEvent는 mouseout이고
onChange의 nativeEvent는 input을 가리키는 것을 확인할 수 있다.

콘솔 출력

+) onMouseLeave와 마찬가지로 onMouseEnter의 nativeEvent도 mouseover이다.
하지만 nativeEvent와 상관없이 enter, leave 에서는 기존 특성처럼 버블링이 일어나지 않는다.

<div
  onMouseEnter={(e) => console.log('enter', e.nativeEvent.type, e.target)}
  onMouseOver={(e) => console.log('over', e.nativeEvent.type, e.target)}
  onMouseOut={(e) => console.log('out', e.nativeEvent.type, e.target)}
  onMouseLeave={(e) => console.log('leave', e.nativeEvent.type, e.target)}
>
    <p>마우스이벤트</p>
</div>

위 요소에서 마우스를 (진입 -> 부모 -> 자식 -> 부모 -> 탈출) 해보면
부모over/부모enter -> 부모out/자식over -> 자식out/부모over -> 부모out/부모leave 순서로
이벤트가 발생함을 알 수 있다.

콘솔출력

참고

profile
🎨프론트엔드 개발자💻

0개의 댓글