BootCamp/모두의연구소:오름캠프

24.02.07

혼복필 2024. 2. 18. 23:06
728x90
300x250
SMALL

안녕하세요, 오랜만에 글을 쓰는 것 같네요.

저번에 말씀드린 DOM의 이벤트의 흐름부터 정리하려 합니다.

사실 이전에 작성하던 글이 있었는데 중간에 날아가서 다시 정리하는 시간이에요..

덕분에 복습도 되고 좋은 것 같습니다 ^-ㅜ..

 

이벤트 흐름

브라우저 화면에서 이벤트 발생 시 브라우저는 가장 먼저 이벤트 대상을 찾음

 

 

대상을 찾아갈 때 상위의 window 객체부터 document, body 순으로 DOM 트리를 따라 내려감

= 캡처링 단계라고 부름

이벤트 대상을 찾아가는 과정에서 브라우저는 중간에 만나는 모든 캡처링 이벤트 리스너를 실행

이벤트 대상을 찾고 캡처링이 끝나면 이제 다시 DOM 트리를 따라 올라가며 만나는 모든 버블링 이벤트 리스너를 실행

= 버블링 단계라고 부름

이러한 과정에서 이벤트 리스너가 차례로 실행되는 것

= 이벤트 전파 (event propagation)라고 부름

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link rel="stylesheet" href="../reset.css">
    <style>
    </style>
</head>
<body>
    <article class="parent">
        <button class="btn" type="button">버튼</button>
    </article>
    <script>
        const parent = document.querySelector('.parent');
        const btnFirst = document.querySelector('.btn');
        btnFirst.addEventListener('click', (event) => {
            console.log("btn capture!");
        })
        window.addEventListener('click', () => {
            console.log("window capture!");
        }, true); // true : 캡처링 단계의 이벤트가 발생하도록 합니다.
        document.addEventListener('click', () => {
            console.log("document capture!");
        }, true);
        parent.addEventListener('click', () => {
            console.log("parent capture!");
        }, true);
        btnFirst.addEventListener('click', (event) => {
            console.log("btn bubble!");
        })
        parent.addEventListener('click', () => {
            console.log("parent bubble!");
        });
        document.addEventListener('click', () => {
            console.log("document bubble!");
        });
        window.addEventListener('click', () => {
            console.log("window bubble!");
        });
    </script>
</body>
</html>

 

이벤트 Target, CurrentTarget

부모부터 자식까지 일련의 요소를 모두 타고 가며 진행되는 이러한 이벤트의 특징

Target : 이벤트가 발생한 진원지의 정보가 담겨 있음

또한 이벤트 리스너가 없는 요소의 이벤트가 발생했을 때도 해당 요소에 접근할 수 있음

CurrentTarget : 이벤트 리스너가 연결된 요소가 참조되어 있음

<article class="parent">
    <ol>
        <li><button class="btn-first" type="button">버튼1</button></li>
        <li><button type="button">버튼2</button></li>
        <li><button type="button">버튼3</button></li>
    </ol>
</article>
<script>
    const parent = document.querySelector('.parent');
    parent.addEventListener('click', function (event) {
        console.log(event.target);
        console.log(event.currentTarget);
    })
</script>


이벤트 위임

이벤트의 흐름을 통해 이벤트 리스너가 없는 요소의 이벤트가 발생했을 때도 해당 요소에 접근할 수 있다는 것을 알게 됨

이를 이용해 이벤트 리스너가 없어도 마치 리스너가 있는 것처럼 사용할 수 있음

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link rel="stylesheet" href="../reset.css">
    <style>
    </style>
</head>
<body>
    <article class="parent">
        <ol>
            <li><button class="btn-first" type="button">버튼1</button></li>
            <li><button type="button">버튼2</button></li>
            <li><button type="button">버튼3</button></li>
        </ol>
    </article>
    <script>
        const parent = document.querySelector('.parent');
        parent.addEventListener('click', function (event) {
            console.log(event.target);
            if (event.target.nodeName === "BUTTON") {
                event.target.textContent = "버튼4";
            }
        })
    </script>
</body>
</html>

 

이벤트의 this

이벤트 리스너 함수 내부에서의 this 값은 이벤트가 연결된 노드를 참조

event.currentTarget 속성의 참조값과 유사

= 이벤트 리스너 함수를 화살표 함수로 쓰면 this가 가리키는 대상이 달라진다는 점에 유의해야 함

<article class="parent">
    <ol>
        <li><button class="btn-first" type="button">버튼1</button></li>
        <li><button type="button">버튼2</button></li>
        <li><button type="button">버튼3</button></li>
    </ol>
</article>
<script>
    const parent = document.querySelector('.parent');
    parent.addEventListener('click', function (event) {
        console.log(this);
    });
const myObj = {
        name: 'jaehyun',
        walk() {
            parent.addEventListener('click', () => {
                console.log(this.name + ' is walking');
            })
        }
    }
</script>

 

preventDefault()

브라우저의 기본 이벤트 동작을 취소

브라우저는 HTML 태그를 통해 여러 가지 기능들을 제공 (하지만 때론 그런 기능이 방해되는 경우가 있음)

= 브라우저의 기본 동작을 중지하고 JavaScript를 통해 기능을 처리하고자 할 때 사용

<!-- 앵커의 기본 동작을 중지 -->
<a href="https://www.naver.com" class="link">네이버 링크입니다만..</a>
<script>
    const link = document.querySelector('.link');
    link.addEventListener('click', (event) => {
        console.log('clicked');
        event.preventDefault();
    })
</script>
<!-- submit 의 기본 동작을 중지 -->
<form action="">
    <button type="submit" class="submit">제출</button>
</form>
<script>
    const submit = document.querySelector('.submit');
    submit.addEventListener('click', (event) => {
        console.log('clicked');
        event.preventDefault();
    })
</script>

+ preventDefault 실습

이벤트 타입 contextmenu를 이용해 브라우저 오른쪽 버튼 이벤트 막고 '해당 페이지에서는 오른쪽 클릭을 제한합니다.' 경고 띄우기

 

stopPropagation()

preventDefault를 통해 브라우저의 기본 이벤트 동작을 취소할 수 있음

하지만 이벤트 흐름, 즉 이벤트 전파 (이벤트 프로파게이션)까지 막지는 못함

<form action="">
    <button type="submit" class="submit">제출</button>
</form>
<script>
    const submit = document.querySelector('.submit');
    submit.addEventListener('click', (event) => {
        console.log('clicked');
        event.preventDefault();
        // event.stopPropagation();
    });
    document.body.addEventListener('click', () => {
        console.log('event still alive!');
    });
</script>

= 이벤트 전파를 막고 싶은 경우 event.stopPropagation() 코드를 추가해야 함

+ stopPropagation() 실습

<h1>나의 todo list</h1>
<p>1. 오늘 저녁에는 부대찌게를 끓여 먹겠다.<button type="button">삭제</button></p>
<p>2. 후식으로 슈팅스타를 먹겠다.<button type="button">삭제</button></p>
<p>3. 자기 전에 반드시 내일 아침 메뉴를 생각해두겠다.<button type="button">삭제</button></p>

1. P 태그를 클릭하면 p 태그의 콘텐츠를 출력하는 alert 창을 띄우기

2. 삭제 버튼을 클릭하면 삭제할 것인지를 물어보는 confirm 창을 띄워주고 확인을 누르면 P태그를 삭제

 

까지 DOM의 기본 이론을 마치겠습니다.

8일에는 Ajax 이론과 설 연휴를 끝난 13일 기준으로 16일까지 진행한 미니 프로젝트에 대해 글을 써보려고 합니다.

필요한 참조 코드는 GitHub 확인해 주세요 :)

https://github.com/soohyun020812/ormcamp

 

GitHub - soohyun020812/ormcamp: 오름캠프 교육에서 활용한 실습 내용들 정리

오름캠프 교육에서 활용한 실습 내용들 정리. Contribute to soohyun020812/ormcamp development by creating an account on GitHub.

github.com

728x90
300x250
LIST

'BootCamp > 모두의연구소:오름캠프' 카테고리의 다른 글

미니 프로젝트  (0) 2024.02.21
24.02.08  (0) 2024.02.19
오름캠프 중간 회고  (6) 2024.02.13
24.02.06  (3) 2024.02.09
24.02.05  (2) 2024.02.08