본문 바로가기
Programming/HTML & CSS & JavaScript

js 4일차 - event(1)

by yoon9i 2024. 5. 8.

###########################################################################
###########################################################################
7장. 이벤트
###########################################################################

1. 이벤트 개요

1> 용어정리
가. 이벤트(event)
- 사용자 및 시스템(웹브라우저)이 특정상황에 발생시키는 사건(동작) 의미.
ex>
    사용자가 마우스를 이용해서 버튼을 클릭/더블클릭/드래그/마우스오버/...
    사용자가 키보드를 이용해서 input 태그에 값을 입력...
    시스템(웹브라우저)가 window(창) 에 html 랜더링하기 위해서
    DOM 트리를 만드는데, DOM 트리가 모두 완성됨을 알 수 있는 정보를 얻을 수 있음.

나. 이벤트타입(event type): 이벤트 종류

    마우스 이용: click, change, mouseover, mouseout, dbclick, ...
    키보드 이용: keyup, keydown, keypress
    포커스 관련: focus, blur(포커스 해제)

    시스템 관련: load

 

다. 이벤트 핸들러(event handler)
- 이벤트가 발생했을 때 실제로 처리하는 코드를 가진 함수 의미.
- ex>
        function fun() {}
        var fun = function(){};

라. 이벤트 소스(event source)
- 이벤트가 발생된 태그(버튼)


2> 이벤트 처리 방법 (이벤트소스와 이벤트 핸들러 연결작업)

가. DOM Level 0
- 인라인 방식
=> html 시작태그에서 연결
=> 시작태그에서 on이벤트타입으로 된 속성이용
ex>
    <button onClick="함수()"></button>

=> 특징은 html 과 JS 분리가 안된 방식으로 권장 안함.

<!DOCTYPE html>
<html lang="en">

<head>
    <title>js10_이벤트처리1_DOMLevel0_인라인방식</title>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script>
        // DOM Level 0 - 인라인방식
        function ok() {
            console.log("ok");
        }
    </script>
</head>


<body onload="ok()"> <!-- 실행시 ok() 호출 -->
    <!-- 버튼클릭시 ok() 호출 -->
    <button onClick="ok()">OK</button><br>
    <!-- 마우스를 버튼에 over 와 out 시에 ok() 호출 -->
    <button onmouseover="ok()" onmouseout="ok()">OK2</button><br>

    <!-- 마우스로 ok2 버튼에 가져갔을때 ok() 호출 -->
    userid: <input type="text" name="userid" onfocus="ok()" onblur="ok()"><br>
    <!-- 누르고있을때 ok() 호출 -->
    passwd1: <input type="text" name="passwd" onkeydown="ok()"><br>
    <!-- 눌렀다가 땟을때 ok() 호출 -->
    passwd2: <input type="text" name="passwd" onkeyup="ok()"><br>
    <!-- enter 로 값을 입력했을때 ok() 호출 -->
    passwd3: <input type="text" name="passwd" onkeypress="ok()"><br>

    <!-- 값이 변경될때 ok() 호출 -->
    <select name="hobby" onchange="ok()">
        <option value="야구">야구</option>
        <option value="축구">축구</option>
        <option value="농구">농구</option>
    </select><br>

    <!-- 체크 or 해제 시 ok() 호출 -->
    <input type="checkbox" onclick="ok()">
</body>

</html>
<!DOCTYPE html>
<html lang="en">

<head>
    <title>js10_이벤트처리1_DOMLevel0_인라인방식2</title>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script>
        // DOM Level 0 - 인라인방식
        function ok(n) {
            console.log("ok", n);
        }

        function ok2(n, n2) {
            console.log("ok", n, n2);
        }

        function ok3(n, n2 = 10, ...n3) {
            console.log("ok", n, n2, n3);
        }
    </script>
</head>


<body>
    <button onclick="ok(100)">OK</button>
    <button onclick="ok2(10,20)">OK2</button>
    <button onclick="ok2(10,20,30,40)">OK2</button>

    <button onclick="ok3(10,20,30,40)">OK3</button>
</body>

</html>
<!DOCTYPE html>
<html lang="en">

<head>
    <title>js10_이벤트처리1_DOMLevel0_인라인방식3_이벤트객체</title>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script>
        // DOM Level 0 - 인라인방식
        function ok() {
            console.log("ok", event);
            console.log(event.target.innerText);
            // event 객체를 사용해서 OK 버튼 과 OK2버튼중에 어느 버튼을 눌렀는지
            // 확인이 가능하다.
        }
    </script>
</head>


<body>
    <button onclick="ok()">OK</button>
    <button onclick="ok()">OK2</button>

</body>

</html>

 

- 고전 방식
=> 특징은 html 과 JS 분리해서 이벤트처리가 됨
=> JS 에서 이벤트소스를 얻고 on이벤트타입을 지정해서 처리
문법:
        - JS
        이벤트소스.onClick = function(){};

        - html
        <button id="x">Ok</button>
        <button id="y">Ok2</button>

 

=> 이벤트소스 얻는 방법 (button)
    document.메서드() 이용

    ex>
        요소 하나 반환하는 경우
        - var result = document.getElementById("x");
                        ..
        - var result = document.querySelector("css의 선택자문법");
        css 의 선택자문법: #id, .class, 태그명, [속성명], 부모 > 자식,

        요소 여러개 반환하는 경우(배열로 반환)
        - var result = document.querySelectorAll("css 의 선택자문법");
        css 의 선택자문법: #id, .class, 태그명, [속성명], 부모 > 자식,

<!DOCTYPE html>
<html lang="en">

<head>
    <title>js10_이벤트처리2_DOMLevel0_고전방식</title>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script>
        // DOM Level 0 - 고전방식
        // document.
        var btn = document.getElementById("x");
        console.log(btn); // null

    </script>
</head>


<body>
    <!-- 
        <head> 에서 null 이 나오는 이유?
        순차문이기때문에 만들기전에 head 태그에서 x 를 찾으면 null 이 나온다.
        단, 무조건 body 태그에서 사용해야하는것이 아닌 head 태그에서도 사용이 가능하다.
    -->
    <button id="x">OK</button><br>
    <script>
        // DOM Level 0 - 고전방식
        // document.
        var btn = document.getElementById("x");
        console.log(btn); // <button> 출력됨

    </script>

</body>

</html>
<!DOCTYPE html>
<html lang="en">

<head>
    <title>js10_이벤트처리2_DOMLevel0_고전방식2</title>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script>
        // DOM Level 0 - 고전방식
        // <head> 태그안에서 DOM 을 접근하기 위해서는
        // onload 이벤트를 사용해서 DOM 이 모두 만들어진 후에 접근하도록 설정해야 됨.
        // onload 없이 접근하면 아직 <body> 태그내의 DOM 이 안만들어졌기 때문에
        // 접근할 수 없음.

        window.onload = init; // 중요: init() 아니다.
        /*
            window.onload = init();
            - dom 이 모두 만들어지면 함수를 호출해야 되는데 init() 으로 쓰면
              DOM 생성여부와 무관하게 바로 호출이 된다.

            window.onload = init;
            - DOM 이 모두 만들어졌을 때 시스템이 init() 호출함.
              콜백함수 방식.
        */

        function init() {
            var btn = document.getElementById("x");
            console.log(btn); // <button id="x">OK</button>
            console.dir(btn); // button#x (Button 객체)
            /*
                DOM (Document(html) object(객체) Model)
                개념: html 의 모든 태그들이 개별적인 객체로 구성되어있고
                      이러한 객체들을 이용해서 JS 에서 핸들링이 가능한 방법론.
            */

            var a = document.getElementById("x2");
            console.dir(a); // HTMLAnchorElement
        }

    </script>
</head>


<body>

    <button id="x">OK</button><br>
    <a href="" id="x2">daum</a>

</body>

</html>
<!DOCTYPE html>
<html lang="en">

<head>
    <title>js10_이벤트처리2_DOMLevel0_고전방식3</title>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script>

        window.onload = init;

        function init() {
            // 방법1>
            // var btn = document.getElementById("x");
            // var btn = document.querySelector("#x"); 
            // - querySelector("css문법(id -> #)")
            // - getElementById 와 같은 동작

            // btn.onclick = function() {
            //     console.log("ok");
            // }

            // 방법2>
            // - 같은 기능인데 함수가 중복되는 문제점이 있음.
            // document.querySelector("#x").onclick = function () {
            //     console.log("ok");
            // };

            // document.querySelector("#x2").onclick = function () {
            //     console.log("ok");
            // };

            // 방법3>
            // - 함수 중복 제거

            var fun = function () {
                console.log("ok");
            };

            document.querySelector("#x").onclick = fun; // 콜백함수 (*)
            // 주의: fun() 은 직접호출이기때문에 콜백함수로 () 없이 fun 을 사용한다. 

            document.querySelector("#x2").onclick = fun; // 콜백함수 (*)
        }

    </script>
</head>


<body>

    <button id="x">OK</button><br>
    <button id="x2">OK2</button><br>

</body>

</html>
<!DOCTYPE html>
<html lang="en">

<head>
    <title>js10_이벤트처리2_DOMLevel0_고전방식4</title>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script>
        // 이벤트 처리
        window.onload = init;

        function init() {
            document.querySelector("#x").onclick = function () { console.log("x"); };
            document.querySelector("#x2").onclick = function () { console.log("x2"); };
            document.querySelector("#userid").onfocus = function () { console.log("userid1"); };
            document.querySelector("#userid").onblur = function () { console.log("userid2"); };
            document.querySelector("#passwd").onkeyup = function () { console.log("passwd"); };
            document.querySelector("#hobby").onchange = function () { console.log("hobby"); };
            document.querySelector("#x3").onclick = function () { console.log("x3"); };
        }

    </script>
</head>


<body>

    <button id="x">OK</button><br>
    <button id="x2">OK2</button><br>


    userid: <input type="text" name="userid" id="userid"><br>
    passwd: <input type="text" name="passwd" id="passwd"><br>



    <select name="hobby" id="hobby">
        <option value="야구">야구</option>
        <option value="축구">축구</option>
        <option value="농구">농구</option>
    </select><br>

    <input type="checkbox" id="x3">

</body>

</html>

 

 

나. DOM Level 2
=> 특징은 html 과 JS 분리해서 이벤트처리가 됨.
=> JS 에서 이벤트소스를 얻고 addEvenetListener() 메서드로 이벤트 처리함.

    문법:
        JS: 이벤트소스.onclick = function(){}; // DOM Level 0
        JS: 이벤트소스.addEvenetListener("이벤트타입", 이벤트핸들러, boolean(false)); // DOM Level 2
            ==> document.querySelector("#x").addEvenetListener("click", function(){});

        html: <button id="x">OK</button>

<!DOCTYPE html>
<html lang="en">

<head>
    <title>js10_이벤트처리2_DOMLevel2_addEventListener</title>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script>
        // DOM Level 2 - addEventListener
        window.onload = init;
        function init() {
            document.querySelector("#x").addEventListener("click", function () {
                console.log("ok 클릭~~~~~~~~");
            }); // DOM Level 2
        }

    </script>
</head>


<body>

    <button id="x">OK</button><br>
    <script>
        // document.querySelector("#x").onclick : DOM Level 0
        document.querySelector("#x").addEventListener("click", function () {
            console.log("ok 클릭");
        }); // DOM Level 2
    </script>


</body>

</html>



==> useCapture 개요
- 기본값은 false
- 이벤트 전파와 관련된 동작방식을 변경하는 용도.
- 이벤트전파는 캡처링(부모->자식) & 버블링(자식->부모) 두가지가 있다.

    a. 자식 ---> 부모
    - 버블링(bubbling) 이라고 부름

    b. 부모 ---> 자식
    - 캡처링(capturing) 이라고 부름

- useCapture 값을 true 로 지정하면 부모 --> 자식으로 전파(캡처링(capturing))으로 동작.
- useCapture 값을 false 로 지정하면 자식 --> 부모으로 전파(버블링(bubbling)) 으로 동작.


==> 이벤트 전파되는 것을 방지가능하다.(event 객체이용)(*)
- 이벤트객체의 stopPropagation() 이용. (event 전파방지 메서드)
ex>
    event.stopPropagation();

 

<!DOCTYPE html>
<html lang="en">

<head>
    <title>js10_이벤트처리2_DOMLevel2_addEventListener2_이벤트전파</title>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">

</head>


<body>
    <div style="background-color: yellow;" id="a">
        a
        <div style="background-color: blue;" id="b">
            b
        </div>
    </div>
    <script>

        document.querySelector("#a").addEventListener("click", function () {
            console.log("a");
        }, true);
        // false 로 지정하면 버블링으로 동작되어 b 출력후 a 출력됨 (자식 -> 부모 전파)
        // true 로 지정하면 캡처링으로 동작되어 a 출력후 b 출력됨 (부모 -> 자식 전파)

        document.querySelector("#b").addEventListener("click", function () {
            console.log("b");
        }, false);

    </script>
</body>

</html>
<!DOCTYPE html>
<html lang="en">

<head>
    <title>js10_이벤트처리2_DOMLevel2_addEventListener2_이벤트전파2_이벤트전파방지_stopPropagation</title>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">

</head>


<body>
    <div style="background-color: yellow;" id="a">
        a
        <div style="background-color: blue;" id="b">
            b
        </div>
    </div>
    <script>

        document.querySelector("#a").addEventListener("click", function () {
            console.log("a");
        }, false);


        document.querySelector("#b").addEventListener("click", function () {
            console.log("b");

            // 이벤트 전파방지
            event.stopPropagation();

        }, false);

    </script>
</body>

</html>

 

3> 이벤트 객체(*)
- 이벤트소소에서 발생되는 이벤트 정보를 관리하는 객체.
- 이벤트 객체를 사용해서 다양한 작업을 할 수 있다.
- 이벤트 객체를 얻는 방법은
  이벤트 핸들러(함수) 에서 event 변수명으로 얻어온다.

ex>
    function fun() {
        console.log(event);
    }