1.  이벤트 설정하기

🐝  이벤트 : 사이트에서 방문자가 취하는 모든 행위
         ▶️  모든 문서 객체는 생성되거나 클릭되거나 마우스를 위에 올리거 나 할 때 이벤트가 발생
🐝  이벤트 핸들러 (= 이벤트 리스너) : 이벤트가 발생했을 때 실행되는 코드 (함수)

 

(1) 이벤트 핸들러 등록 종류


  1) 이벤트 핸들러 어트리뷰트 방식

 

    👩🏻‍💻 이벤트 핸들러 어트리뷰트는 onclick과 같이 on 접두사와 이벤트의 종류를 나타내는 이벤트 타입으로 이루어져 있음
    👩🏻‍💻  주의할 점은 이벤트 핸들러 어트리뷰트 값으로 함수 참조가 아닌 함수 호출문 등의 문을 할당
           ➡️  이때 이벤트 핸들러 어트리뷰트 값은 사실 암묵적으로 생성될 이벤트 핸들러의 함수 몸체를 의미
           ➡️  하지만 HTML과 자바 스크립트는 관심사가 다르므로 혼재하는 것보다 분리하는 것이 좋음

<body>
    <button onclick="sayHi('Lee')">Click me!</button>
    <script>
        function sayHi(name) {
            console.log(`Hi! ${name}`); // Hi! Lee
        }
    </script>
</body>

 



  (2) 이벤트 핸들러 프로퍼티 방식

 

    👩🏻‍💻  window 객체와 Document, HTMLElement 타입의 DOM 노드 객체는 이벤트에 대응하는

          이벤트 핸들러 '프로퍼티'를 가지고 있음
    👩🏻‍💻  이벤트 핸들러 프로퍼티의 키는 on 접두사와 이벤트의 종류를 나타내는 이벤트 타입으로 이루어져 있음
    👩🏻‍💻  이벤트 핸들러 프로퍼티 방식은 이벤트 핸들러 어트리뷰트 방식의 HTML과 자바 스크립트가 뒤섞이는 문제를 해결할 수 있음
           ▶️ 하지만 이벤트 핸들러 프로퍼티에 하나의 이벤트 핸들러만 바인딩할 수 있다는 단점이 있음

<body>
    <button>Click me!</button>
    <script>
        const btn = document.querySelector('button');
        console.log(typeof btn); // object

        // 이벤트 핸들러 프로퍼티에 이벤트 핸들러 바인딩.
        // 첫 번째로 바인딩 된 이벤트 핸들러는 두 번째 바인딩된 이벤트 핸들러에 의해 재할당되어 실행되지 않음.
        btn.onclick = function () {
            console.log('button click 1');
        };

        btn.onclick = function () {
            console.log('button click 2');
        };
    </script>
</body>

 


 

  (3)  addEventListener 메서드 방식

 

문서 객체.addEventListener(이벤트 이름, 콜백 함수)
      ⚡️  첫 번째 매개변수에는 이벤트의 종류를 나타내는 문자열인 이벤트 타입을 전달
             ( 이 때 이벤트 핸들러 프로퍼티 방식과는 달리 on 접두사를 붙이지 않음 )
      ⚡️  두 번째 매개변수에는 이벤트 핸들러를 전달


     👩🏻‍💻  DOM Level 2에서 도입된 Event.prototype.addEventListener 메서드를 사용하여 이벤트 핸들러를 등록할 수 있음
     👩🏻‍💻  '이벤트 핸들러 어트리뷰트 방식'과 '이벤트 핸들러 프로퍼티 방식'은 DOM Level 0 부터 제공되던 방식

<body>
    <button>Click me!</button>
    <script>
        const btn = document.querySelector('button');

        btn.addEventListener('click', function () {
            console.log('button click 1');
        });  // 재활용 불가

        function btnClick () {
            console.log('button click 2');
        } // 재활용 가능

        btn.addEventListener('click', btnClick);

    </script>
</body>

이벤트 핸들러 프로퍼티 방식과 addEventListener 메서드 방식을 모두 사용하여 이벤트 핸들러를 등록하면?

 

    addEventListener 메서드 방식은 이벤트 핸들러 프로퍼티에 바인딩된 이벤트 핸들러에 아무 영향을 주지 않음
    따라서 버튼 요소에서 클릭 이벤트가 발생하면 2개의 이벤트 핸들러가 모두 호출

<body>
    <button>Click me!</button>
    <script>
        const btn = document.querySelector('button');
        
        // 이벤트 핸들러 프로퍼티 방식.
        btn.onclick = function () {
            console.log('[이벤트 핸들러 프로퍼티 방식] button click');
        }

        // addEventListener 메서드 방식.
        btn.addEventListener('click', function () {
            console.log('[addEventListner 메서드 방식] button click');
        });
    </script>

</body>

💫  addEventListener 메서드는 동일한 요소에서 발생한 동일한 이벤트에 대해 하나 이상의 이벤트 핸들러를 등록할 수 있음
<body>
<button>Click me!</button>
<script>
    const btn = document.querySelector('button');

    function btnClick () {
            console.log(`button click`);
    }

    btn.addEventListener('click', btnClick);
    btn.addEventListener('click', btnClick);

</script>
</body>

응용 예제
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script>

        document.addEventListener('DOMContentLoaded', () => {
            const h1 = document.querySelector('h1');
            let counter = 0;

            h1.addEventListener('click', function (event) { 
            // h1 태그에 click 이벤트가 발생할 때 실행할 함수.
                counter++;
                h1.textContent = `클릭 횟수: ${counter}`;
            });
        });
    </script>
    <style>
        h1 { /* 클릭을 여러 번 했을 때 글자가 선택되는 것을 막기 위한 스타일. 드래그가 안됨 */
            user-select: none;
            cursor: pointer;
        }
    </style>

</head>
<body>
    <h1>클릭 횟수: 0</h1>
</body>


(2) 이벤트 핸들러 제거

 

문서 객체.removeEventListener(이벤트 이름, 콜백 함수)

 

  👩🏻‍💻  addEventListener 메서드로 등록한 이벤트 핸들러를 제거하려면

        EventTarget.prototype.removeEventListener() 메서드를 사용 
  👩🏻‍💻  removeEventListener 메서드에 전달할 인수는 addEventListener 메서드와 동일
  👩🏻‍💻  addEventListener 메서드에 전달한 인수와 removeEventListener 메서드에 전달한 인수가 일치하지 않으면
        이벤트 핸들러가 제거되지 않음  ➡️ 
익명함수를 이벤트 핸들러로 등록한 경우에는 제거할 수 없음
       ⚡️ 단, 기명 이벤트 핸들러 내부에서 removeEventListener 메서드를 호출하여 이벤트 핸들러를 제거하는 것은 가능
            (이때 이벤트 핸들러는 단 한 번만 호출)

<body>
    <button>Click me!</button>
    <script>
        const btn = document.querySelector('button');

        const handleClick = () => console.log('button click');

        // 이벤트 핸들러 등록
        btn.addEventListener('click', handleClick);

        // 이벤트 핸들러 제거
        btn.removeEventListener('click', handleClick, true); // 실패
        btn.removeEventListener('click', handleClick); // 성공
    </script>
</body>

기명 이벤트 핸들러 내부에서 removeEventListener 메서드를 호출하여 이벤트 핸들러를 제거
<body>
<button>Click me!</button>
<script>

    const btn = document.querySelector('button');

    btn.addEventListener('click', function foo() {
        console.log('button click');

        // 이벤트 핸들러를 제거. 따라서 이벤트 핸들러는 단 한 번만 호출.
        btn.removeEventListener('click', foo);
    });

</script>
</body>

 

프로퍼티 방식으로 이벤트 핸들러 등록한 경우 removeEventListener 메서드로 제거 불가

 

    💫  프로퍼티에 'null' 할당하여 제거

<body>
    <button>Click me!</button>
    <script>
        const btn = document.querySelector('button');
        const handleClick = () => console.log('button click');

        // 이벤트 핸들러 프로퍼티 방식으로 이벤트 핸들러 등록
        btn.onclick = handleClick;

        // removeEventListener 메서드로 이벤트 핸들러를 제거할 수 없음.
        btn.removeEventListener('click', handleClick);

        // 이벤트 핸들러 프로퍼티에 null을 할당하여 이벤트 핸들러를 제거.
        btn.onclick = null;
    </script>
</body>

예제

 

<body>
    <button id="changeBtn">배경색 변경</button>
    <button id="resetBtn">배경색 초기화</button>
    <script>
        const changeBtn = document.querySelector('#changeBtn');
        const resetBtn = document.querySelector('#resetBtn');

        let i = 0;

        const bodyTag = document.querySelector('body');
        const color = ['red', 'orange', 'yellow', 'blue'];
        const handleColor = () => {
            bodyTag.style.backgroundColor = color[i++ % color.length];
        }

        changeBtn.addEventListener('click', handleColor);
        resetBtn.addEventListener('click', () => {
            changeBtn.removeEventListener('click', handleColor);
            bodyTag.style.backgroundColor = '';
        })
    </script>
</body>

 


응용 예제
<head>
    <script>

        document.addEventListener('DOMContentLoaded', () => {
            const h1 = document.querySelector('h1');
            const btnConnect = document.getElementById('connect');
            const btnDisconnect = document.getElementById('disconnect');
            const p = document.querySelector('p');

            let counter = 0;
            let isConnect = false; // 이벤트를 여러 번 연결되지 않게

            const listener = (event) => { // 이벤트를 제거하려면 이벤트 리스너를 변수 또는 상수로 가지고 있어야 함.
                h1.textContent = `클릭 횟수: ${counter++}`;
            }

            btnConnect.addEventListener('click', function () {
                if (isConnect === false) {
                    // 1. h1에 이벤트 리스너 연결
                    h1.addEventListener('click', listener);

                    // 2. btnConnect 버튼 안 보이도록
                    this.style.display = 'none';
                    btnDisconnect.style.display = 'block';

                    // 3. p의 내용을 '이벤트 연결 상태 : 연결'로 변경
                    p.textContent = '이벤트 연결 상태: 연결';

                    isConnect = true;
                }
            });

            btnDisconnect.addEventListener('click', function () {
                if (isConnect === true) {
                    // 1. h1에 이벤트 리스너 해제
                    h1.removeEventListener('click', listener);

                    // 2. btnDisconnect 버튼 안 보이도록
                    btnConnect.style.display = 'block'
                    this.style.display = 'none';

                    // 3. p의 내용을 '이벤트 연결 상태 : 해제'로 변경
                    p.textContent = '이벤트 연결 상태: 해제';

                    isConnect = false;
                }
            })

        });
    </script>
    <style>
        h1 {
            user-select: none;
            cursor: pointer;
        }
    </style>
</head>
<body>
    <h1>클릭 횟수: 0</h1>
    <button id="connect">이벤트 연결</button>
    <button id="disconnect">이벤트 제거</button>
    <p>이벤트 연결 상태: 해제</p>
</body>

 

 

 

 

 

 

 

[ 내용참고 : IT 학원 강의 및 책 '혼자 공부하는 자바스크립트' ]

+ Recent posts