# 이벤트 버블링(Event Bubbling)

이번엔 이벤트 버블링을 배워볼껀데

우선 js012.html 파일을 만들고 js010.html의 일부만 가져옵니다.

(캐러셀 return 스크롤이벤트  부분 제외)



{% code title="js012.html" %}
```javascript
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>

    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-4bw+/aepP/YC94hEpVNVgiZdgIC5+VKNBQNGCHeKRQN+PtmoHDEXuppvnDJzQIu9" crossorigin="anonymous">

    <link rel="stylesheet" href="main.css">
    <script src="https://code.jquery.com/jquery-3.7.0.min.js" integrity="sha256-2Pmvv0kuTBOenSvLm6bvfBSSHrUJ+3A7x6P5Ebd07/g=" crossorigin="anonymous"></script>
</head>
<body>
    <div class="black-bg1">
        <div class="white-bg">
            <h4>로그인하세요</h4>
            <form >
                <div class="mb-3">
                    <input type="text" class="form-control" id="email">
                    <!--<input type="email" class="form-control" id="email1">-->
                </div>
                <div class="mb-3">
                    <input type="password" class="form-control" id="password">
                </div>
                <button type="submit" id="submit" class="btn btn-primary">Submit</button>
                <button type="button" class="btn btn-danger" id="close">닫기</button>
            </form>

        </div>
    </div>

    <nav class="navbar navbar-light bg-light">
        <div class="container-fluid">
            <a class="navbar-brand" href="#">Offcanvas navbar</a>
            <span class="badge bg-dark ms-auto mx-3">Dark 🌛</span>
            <button class="navbar-toggler" type="button">
                <span class="navbar-toggler-icon "></span>
            </button>
        </div>
    </nav>

    <ul class="list-group" id="list1">
        <li class="list-group-item">An item</li>
        <li class="list-group-item">A second item</li>
        <li class="list-group-item">A third item</li>
        <li class="list-group-item">A fourth item</li>
        <li class="list-group-item">And a fifth one</li>
    </ul>

    <button id="loginBtn" type="button" class="btn btn-primary">
        버튼
    </button>

    <script>
        $('#loginBtn').on('click', function(){
            $('.black-bg1').addClass('show-modal1');

        });

        $('#close').on('click', function() {
            $('.black-bg1').removeClass('show-modal1');
        })

        $('.navbar-toggler').on('click', function() {
            $('.list-group').toggleClass('lg-open');
        });


        $('form').on('submit', function (e){
            console.log(document.getElementById('email').value);
            if($('#email').val() === ''){
                alert('아이디를 입력하세요');
                e.preventDefault();  // 폼 전송 막는 코드
            }

            var regExp = /^([\w\.\_\-])*[a-zA-Z0-9]+([\w\.\_\-])*([a-zA-Z0-9])+([\w\.\_\-])+@([a-zA-Z0-9]+\.)+[a-zA-Z0-9]{2,8}$/i;

            if(!regExp.test($('#email').val())){
                alert("이메일 형식을 확인하세요");
                e.preventDefault();
            }

            if($('#password').val() == ''){
                alert('패스워드를 입력하세요');
            }else if($('#password').val().length <4){
                alert('패스워드는 4자 이상이어야 합니다.');
            }


        });
    </script>
</body>
</html>
```
{% endcode %}



<figure><img src="https://3814826491-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FJyHOwztPxBT3bLpisjCt%2Fuploads%2FHpiAEvu12rPaR7oEw0yT%2FScreenshot_7.png?alt=media&#x26;token=267198a0-dac0-4918-a657-b970b08ff073" alt=""><figcaption></figcaption></figure>

회색 부분을 클릭 했을 때 모달이 닫히는 걸 만들어보자.&#x20;



```javascript
 $('.black-bg1').on('click' , function (){
      $('.black-bg1').removeClass('show-modal1');
  });
```

이렇게 하면 배경 클릭 시 잘 닫힌다.

🔥 이렇게 하면 버그가 있다. input box나 흰배경을 클릭 해도 닫힌다.&#x20;



<figure><img src="https://3814826491-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FJyHOwztPxBT3bLpisjCt%2Fuploads%2FRkeFMKX3NWQlbUjbhTUS%2FScreenshot_8.png?alt=media&#x26;token=8e4db9ee-051e-404b-92dd-5e282543382a" alt=""><figcaption><p>이벤트 버블링 - 이벤트가 상위 html로 퍼지는 현상</p></figcaption></figure>

&#x20;

<figure><img src="https://3814826491-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FJyHOwztPxBT3bLpisjCt%2Fuploads%2FFd9OwGyGrZpK7mnln9GH%2FScreenshot_70.png?alt=media&#x26;token=5bb9ca88-e66b-4695-9f24-c337e7687c3a" alt=""><figcaption></figcaption></figure>



💎이벤트 관련 함수&#x20;

<pre class="language-javascript"><code class="lang-javascript"><strong>e.target();            //유저가 실제로 누른거
</strong>e.currentTarget();     //이벤트 리스너 달린 곳   $('.black-bg1') 나올듯 
console.log(this);
e.preventDefault();    //이벤트 기본동작 막아줌   10번파일에서 잠깐 보고 넘어감
e.stopPropagation();   //내 상위요소로 이벤트 버블링 막아줌
</code></pre>

{% embed url="https://developer.mozilla.org/ko/docs/Web/API/Event" %}
event&#x20;
{% endembed %}

```javascript
$('.black-bg1').on('click' , function (e){
    //1. jQuery
    if($(e.target).is($('.black-bg1'))){
        $('.black-bg1').removeClass('show-modal1');
    }
    //2. querySelect
    if($(e.target) == document.querySelector('.black-bg1')){
        $('.black-bg1').removeClass('show-modal1');
    }
});
```



지난번에 만들었던 탭기능 js011.html 로 돌아와서

{% code title="app.js" %}
```javascript
for (let i = 0; i< tabBtn.length; i++){
    tabBtn.eq(i).on('click', function (){
        tabBtn.removeClass('orange');
        tabContent.removeClass('show');
        tabBtn.eq(i).addClass('orange');
        tabContent.eq(i).addClass('show');

    })
}
```
{% endcode %}

위의 코드는 이벤트 리스너를 3번 반복해서 생성한다.&#x20;

이걸 다시 줄여보자.&#x20;



{% code title="app.js" %}
```javascript
for (let i = 0; i< tabBtn.length; i++){
    tabBtn.eq(i).on('click', function (){
        tabOpen(i);
    })
}

function tabOpen(num){
    tabBtn.removeClass('orange');
    tabContent.removeClass('show');
    tabBtn.eq(num).addClass('orange');
    tabContent.eq(num).addClass('show');
}
```
{% endcode %}

이렇게 변경 할 수 있다.

이처럼 코드 결과의 변경 없이 구조를 바꾸는 걸 리팩토링이라고 한다.

이렇게 하는 이유는

1. 재사용이 편리
2. 가독성이 좋다 = 다른사람이 코드를 봐도 이해, 수정이 편하다.



이벤트 버블링에 대해서 알면 이벤트 리스너도 줄일 수 있다.&#x20;

탭을 만들면서 이벤트 리스너를 3개를 만들었는데&#x20;

이벤트 버블링을 배우고 나니 하나로도 가능할 것 같다.



```
<ul class="list">
```

&#x20;버튼의 부모인 ul 에 하나의 이벤트 리스너만 있어도 탭기능을 완성할 수 있다.

이렇게 하는 이유는

1. 버튼이 3개에서 더 늘어난다면 추가도 쉽고 코드도 덜 복잡하다.
2. 이벤트리스너는 램을 차지한다 즉 이벤트리스너를 줄이면 성능도 개선된다.



✨ 과제. 방금 작성한 tapOpen 함수를 사용해서 ul $('list') 에 이벤트 리스너를 만들어보자.&#x20;

&#x20;   기존의 이벤트 리스너는 주석처리!



<figure><img src="https://3814826491-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FJyHOwztPxBT3bLpisjCt%2Fuploads%2FvnpaFDbl8vSWI4GJX9BJ%2Fcodemonkey.webp?alt=media&#x26;token=1500874e-591d-4e88-8c43-2a31df7ff462" alt=""><figcaption></figcaption></figure>

밑에 코드 그대로 복붙하거나 따라치면 코드몽키!

직접 고민하고 코드짜서 사람이 되보자.



```javascript
$('.list').click(function(e){
  if (e.target == document.querySelectorAll('.tab-button')[0] ){
    tabOpen(0)
  }
  if (e.target == document.querySelectorAll('.tab-button')[1] ){
    tabOpen(1)
  }
  if (e.target == document.querySelectorAll('.tab-button')[2] ){
    tabOpen(2)
  }
})

```







