Frontend 프론트엔드

[ 30 ] 이벤트 버블링

박민우_ 2024. 6. 22. 16:26

나의 답안 

const onClickAlert = (e: any) => {
    alert(`${e.target.id}님이 작성한 글입니다`);
  };

  return (
    <div>
      {data?.fetchBoards.map((el: any) => (
        <div onClick={onClickAlert} id={el.writer}>
          <input type="checkbox"></input>
          <span style={{ margin: "10px" }}>{el.number}</span>
          <span style={{ margin: "10px" }}>{el.writer}</span>
          <span style={{ margin: "10px" }}>{el.title}</span>
        </div>
      ))}
    </div>
  );

문제 상황 

이벤트 버블링 ( 특정 요소에서 이벤트가 발생하면 그 이벤트는 해당 요소에서 시작하여 부모 요소들을 거쳐 최상위 요소 까지 전달 된다 )

이 현상으로 바깥쪽의 div뿐만 아니라 안쪽 span을 누르면 span과 div에 이벤트가 모두 전달된다. 이때 e.target은 가장 안쪽 요소인 span 이 된다.

해결방법 

e.currentTarget 을 사용한다 

' e.currentTarget ' 은 이벤트 핸들러가 부착된 요소를 가리킨다.

 

' e.target.value ' 이벤트가 실제로 발생한 요소를 가리킨다.

 

 

이벤트 버블링을 막는 방법 

이벤트 버블링시 : 3 , 2, 1 차례로 출력

e.stopPropagation() 을 사용한다 : 3번만 출력

const qqq1 = () => {
    alert("1번클릭");
  };
  const qqq2 = () => {
    alert("2번클릭");
  };
  const qqq3 = (e: any) => {
    e.stopPropagation();
    alert("3번클릭");
  };
  const qqq4 = () => {
    alert("4번클릭");
  };

  return (
    <div>
      {data?.fetchBoards.map((el: any) => (
        <div id={el.writer} onClick={qqq1}>
          <span onClick={qqq2}>
            <input type="checkbox" onClick={qqq3}></input>
          </span>
          <span style={{ margin: "10px" }}>
            {el.number} onClick={qqq4}
          </span>
          <span style={{ margin: "10px" }}>{el.writer}</span>
          <span style={{ margin: "10px" }}>{el.title}</span>
        </div>
      ))}
    </div>
  );

컴포넌트와 이벤트 버블링

컴포넌트에도 이벤트 버블링 현상이 생긴다.

 

import { useQuery, gql } from "@apollo/client";
import { title } from "process";
import { writer } from "repl";
import Checkbox from "./checkbox";
const FETCH_BOARDS = gql`
  query {
    fetchBoards {
      number
      writer
      title
      contents
    }
  }
`;

export default function StaticRoutingMovedPage() {
  const { data } = useQuery(FETCH_BOARDS);

  console.log(data?.fetchBoards);

  // const onClickAlert = (e: any) => {
  //   alert(`${e.currentTarget.id}님이 작성한 글입니다`);
  // };
  const qqq1 = () => {
    alert("1번클릭");
  };

  const qqq4 = () => {
    alert("4번클릭");
  };

  return (
    <div>
      {data?.fetchBoards.map((el: any) => (
        <div id={el.writer} onClick={qqq1}>
          <Checkbox />
          <span style={{ margin: "10px" }}>
            {el.number} onClick={qqq4}
          </span>
          <span style={{ margin: "10px" }}>{el.writer}</span>
          <span style={{ margin: "10px" }}>{el.title}</span>
        </div>
      ))}
    </div>
  );
}

 

export default function Checkbox() {
  const qqq2 = () => {
    alert("2번클릭");
  };
  const qqq3 = (e: any) => {
    e.stopPropagation();
    alert("3번클릭");
  };

  return (
    <span onClick={qqq2}>
      <input type="checkbox" onClick={qqq3}></input>
    </span>
  );
}
728x90