원지의 개발
article thumbnail
728x90

이벤트 객체

  • 모든 이벤트에서 이벤트 객체 사용 가능 (꼭 다중 이벤트 상황이 아니어도 가능)

< 약속 > 이벤트 발생시 실행되는 함수의 (인자값, 첫번째 매개변수)로 현재 실행되는 event 객체를 넣어줌

이벤트 객체의 기능
stopPropagation() 이벤트 전파를 막음 (버블링 중단하기) 굳이 사용x
target 이벤트를 적용한 타겟 속성 클릭한 대상, 선택한 것
currentTarget 실제 이벤트가 걸려있는 타겟 속성 부모의 위치
preventDefault() 태그의 고유 이벤트 제거 a, submit 태그 같은 경우
모달창 띄우고 싶을 때 새로운 페이지로 안 넘어가게끔

이벤트 전파 (a.k.a 상속)

  • 부모에 하나의 이벤트만 걸어 놓으면, 모든 이벤트가 동일하게 자식으로 위임
  • li에 일일히 이벤트를 등록하는 작업을 없앨 수 있음

이벤트 위임

  • 부모에 이벤트를 걸어 두면 자식이 동일한 이벤트를 위임받음
  • li에 일일히 이벤트를 등록하는 작업을 없앨 수 있음
이벤트 실행방식

1. 캡쳐링 ▶ 2. target ▶ 3. 버블링
누르면 올라가면서(버블링 하면서) 부모 이벤트를 실행시켜 주고 감

기본적으로 선언하는 이벤트 함수는 버블링으로 실행
둘 다 실행하면 2번 하니까 캡쳐링에서는 X

 

 

이벤트 버블링

  • DOM의 이벤트 동작 방식
  • 부모, 자식 모두 이벤트가 걸려있을 때, 자식 ▶ 부모 실행

이벤트 캡쳐링

  • 부모, 자식 모두 이벤트가 걸려있을 때, 부모 ▶ 자식 실행
    addEventListener()로만 구현 가능 (구현할 일 X)

 

 

 

클릭을하면 window객체에서 탐색을 하면서 어디서 발생했는지 알아봄 - capturing 

타겟이 확인되면 어디에서 일어났는지 window에게 알려주기 위해 올라감 - bubbling


실습

더보기

1. 여러 이벤트를 한번에 걸어주기 - 반복문 사용 (비효율적)

<!DOCTYPE html>
<html lang="en">
<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>
</head>
<body>

    <h3>여러 이벤트를 한번에 걸어주기</h3>
    
    <ul>
        <li class="item">1.일인자</li>
        <li class="item">2.이인자</li>
        <li class="item">3.삼인자</li>
        <li class="item">4.사인자</li>
        <li class="item">5.오인자</li>
    </ul>

    선택한 태그의 값:
    <p class="result"></p>


    <!-- all로 li를 다 얻어서 반복문으로 하나씩 이벤틀 걸어주면 됨 -->
    <script>
        var result = document.querySelector(".result");

        var item = document.querySelectorAll(".item"); //li 전부 얻어오기, 배열임

        //이 방법은 비효율적인 방법 - 태그 100000개 이상이라면 ~??, 좋은 코드가 아님
        for(var i = 0; i < item.length; i++) {

            item[i].onclick = function() { //item의 i번째를 클릭하면~
                result.innerHTML = this.innerHTML; //this 현재 클릭한 li의 innerHTML을 result.innerHTML에 넣어줌
            }

        }
    </script>

</body>
</html>

2. 이벤트 전파 특성 활용하기

<!DOCTYPE html>
<html lang="en">
<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>
</head>
<body>

    <h3>이벤트 전파 특성 활용하기</h3>
    
    <ul class="parent">
        <li>1.일인자</li>
        <li>2.이인자</li>
        <li>3.삼인자</li>
        <li>4.사인자</li>
        <li>5.오인자</li>
    </ul>

    선택한 태그의 값:
    <p class="result"></p>

    <script>
        var result = document.querySelector(".result");

        //부모에 이벤트를 걸면 자식한테 이벤트가 전파됨
        var parent = document.querySelector(".parent"); //ul
        parent.onclick = function(e) {
            // console.log(this); //this는 ul
            // result.innerHTML = this.innerHTML; //1~5까지 한번에 다 들어옴

            // 이벤트 객체 - 이벤트 함수에 첫번째 매개변수로 자동 전달 됨
            // console.log(e); //1. 매개변수로 받거나
            // console.log(event); //2. 직접 event 객체를 넣거나

            // console.log(event.target); //이벤트가 동작된 실제 태그
            // console.log(event.currentTarget); //실제 이벤트가 걸려있는 태그

            // e.target //li태그

            // console.dir(e.target); //tagName 확인방법
            if(e.target.tagName != "LI") return; //li태그가 아니라면 종료
            result.innerHTML = e.target.innerHTML;
        }
    </script>

</body>
</html>

3. 이벤트 객체 활용

<!DOCTYPE html>
<html lang="en">
<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>

    <style>
        ul li {
            display: inline-block;
        }
    </style>

</head>

<body>
 
    <h3>이벤트객체활용</h3>
    <div>
        <ul class="parent"> <!-- 부모 태그에 class -->
            <li><img src="img/1.jpg" alt="1" width="100"></li>
            <li><img src="img/2.jpg" alt="1" width="100"></li>
            <li><img src="img/3.jpg" alt="1" width="100"></li>
            <li><img src="img/4.jpg" alt="1" width="100"></li>
        </ul>
        결과:
        <div class="result">
            <img src="img/1.jpg" alt="결과" width="300" >
        </div>
    </div>

    <script>
        var result = document.querySelector(".result > img"); //result-img의 scr속성을 변경해야 하기 때문에

        var parent = document.querySelector(".parent");
        parent.onclick = function() {
            // console.log(event.target); //클릭한 li값, 현재 result값
            // console.dir(event.target); //tagName 확인방법

            if(event.target.tagName != "IMG") return; //li태그가 아니라면 종료
            result.src = event.target.src; //클릭한 li의 scr를 result.src에 넣어줌
        }
    </script>


</body>
</html>

4. 이벤트 위임 이용

 

<!DOCTYPE html>
<html lang="en">
<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>

    <style>
        ul li {
            display: inline-block;
        }
		table { border-collapse: collapse; border-spacing : 0;}
        thead th, tbody td {
            border: 1px solid black;
        }
    </style>

</head>
<body>

    <h2>이벤트 위임 이용해서 다음을 만들어 보세요.<h2>

    <table>
        <thead>
            <tr>
                <th>번호</th>
                <th>제목</th>
                <th>내용</th>
                <th>삭제</th>
            </tr>
        </thead>
        <tbody class="list">
            <tr>
                <td>1</td>
                <td>첫글</td>
                <td>hi</td>
                <td><button type="button" class="btn">삭제</button></td>
            </tr>
            <tr>
                <td>2</td>
                <td>첫글</td>
                <td>hi</td>
                <td><button type="button" class="btn">삭제</button></td>
            </tr>
            <tr>
                <td>3</td>
                <td>첫글</td>
                <td>hi</td>
                <td><button type="button" class="btn">삭제</button></td>
            </tr>
            <tr>
                <td>4</td>
                <td>첫글</td>
                <td>hi</td>
                <td><button type="button"  class="btn">삭제</button></td>
            </tr>
        </tbody>
    </table>
    
    <script>
        //삭제 버튼의 공통적인 부모인 tbody에 동작을 걸어야 함 (tr은 삭제버튼마다 다름)
        var list = document.querySelector(".list"); //tbody 부모 클래스 가져옴, 표 다 가져오기

        list.onclick = function() {
            console.log(event.target); //누른 button임
            
            if(event.target.tagName != "BUTTON") return; //버튼일때만 동작
            event.target.parentElement.parentElement.remove(); //tr삭제
        }
    </script>

</body>
</html>

5. 

<!DOCTYPE html>
<html lang="en">
<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>

    <style>
        .func1 {width: 300px; height: 300px; background-color: rgb(255, 58, 58);}
        .func2 {width: 200px; height: 200px; background-color: rgb(77, 88, 247);}
        .func3 {width: 100px; height: 100px; background-color: chartreuse;}
    </style>

</head>
<body>
    
    <div class="func1">
        <div class="func2">
            <div class="func3"> func3자식 </div>
        </div>
    </div>

    <script>
        /*
        DOM에서 이벤트 동작방식은 기본으로 버블링 입니다.
        버블링 - 부모, 자식 모두에 이벤트가 있을 때 이벤트가 자식 → 부모 방향으로 전파되는 특징

        3번 클릭 - 3 ▶ 2 ▶ 1로 실행
        */
        // var func1 = document.querySelector(".func1");
        // func1.onclick = function() {
        //     alert("func1");
        // }

        // var func2 = document.querySelector(".func2");
        // func2.onclick = function() {
        //     // event.stopPropagation(); //이벤트 버블링 중단, 3번 누르면 3 ▶ 2 실행, 거의 안씀
        //     alert("func2");
        // }

        // var func3 = document.querySelector(".func3");
        // func3.onclick = function() {
        //     alert("func3");
        // }


        /*
        이벤트 캡쳐링 - 부모, 자삭에 이벤트가 있을 때, 부모 ▶ 자식으로 전파되는 특징
        addEventListener() 방식으로만 구현해 줄 수 있습니다.
        */

        var func1 = document.querySelector(".func1");
        var func2 = document.querySelector(".func2");
        var func3 = document.querySelector(".func3");   
        
        func1.addEventListener("click", function() {
            alert("func1");
        }, true);

        func2.addEventListener("click", function() {
            alert("func2");
        }, true);

        func3.addEventLis3ener("click", function() {
            alert("func1");
        }, true);

        /* 이 방식으로 하면 fun3을 클릭해도 func1 ▶ 2  ▶ 3 순서로 진행 */

    </script>


</body>
</html>

 

6.

<!DOCTYPE html>
<html lang="en">
<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>



</head>
<body>
    
    <section id="section">
        <div class="list">
            <div>
                <span>홍길동</span>
                <button type="button" class="btn sel">선택</button>
                <button type="button" class="btn del">삭제</button>
                <button type="button" class="btn aaa">aaa</button>
            </div>
            <div>
                <span>김길동</span>
                <button type="button" class="btn sel">선택</button>
                <button type="button" class="btn del">삭제</button>
                <button type="button" class="btn aaa">aaa</button>
            </div>
            <div>
                <span>홍길자</span>
                <button type="button" class="btn sel">선택</button>
                <button type="button" class="btn del">삭제</button>
                <button type="button" class="btn aaa">aaa</button>
            </div>
        </div>
    </section>

    <script>
        var list = document.querySelector(".list");
        list.onclick = function () {
            
            if(event.target.tagName != "BUTTON") return; //버튼이 아니라면 종료
            // console.log(event.target.className); //버튼의 className
            // console.log(event.target.classList); //버튼의 class 이름 list

            var arr = event.target.classList;
            // 각각의 버튼의 동작이 다르기 때문에 class 속성 이용
            if(arr.contains("sel")) {//선택버튼
                event.target.previousElementSibling.style.color = "blue";

            } else if(arr.contains("del")) { //삭제버튼
                event.target.parentElement.remove();

            } else if(arr.contains("aaa")) { //aaa버튼

            }

        }
        
    </script>

</body>
</html>

7.

<!DOCTYPE html>
<html lang="en">
<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>
</head>
<body>
    
    <div>
        <ul class="page">
            <li><a href="list.board">1</a></li>
            <li><a href="list.board">2</a></li>
            <li><a href="list.board">3</a></li>
            <li><a href="list.board">4</a></li>
            <li><a href="list.board">5</a></li>
        </ul>
    </div>

    <script>
        var page = document.querySelector(".page");
        page.onclick = function() {

            event.preventDefault(); //a태그 or submit이 가진 기본이벤트를 중단
            if(event.target.tagName != "A") return; //A가 아니라면 종료
            
            console.log(event.target.innerHTML);    
        }
    </script>

    <hr>

    <form action="https://www.naver.com">
        <input type="text" name="age">
        <input type="submit" value="클릭" id="btn">
    </form>

    <script>
        var btn = document.getElementById("btn");
        btn.onclick = function () { 
            
            event.preventDefault(); //submit의 고유이벤트 중단
            //처리하면 됨

        }
    </script>

</body>
</html>

data - (하이픈) ▶ 교안 x

  • 어떤 값이던지 json으로 저장 가능
  • 태그의 dataset 속성 - 태그의 저장소
  • data - 으로 시작하고, 뒤에 오는 이름은 자유롭게 작성
  • 태그에 값을 저장할 수 있는 저장소 - 태그 안의 값을 찾아 쓰기 위해
data - 이름 마음대로 = "문자열"
data - 이름 마음대로 = '{ id: 1, age:20 }' //필요한 정보 저장 가능

실습

<!DOCTYPE html>
<html lang="en">
<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>
</head>
<body>
    
    <h3>태그의 dataset 속성 - 태그의 저장소</h3>

    <ul class="list">
        <li><a href="#" data-user-info='{"id": "1", "age":"10"}'>홍길동</a></li>
        <li><a href="#" data-user-info='{"id": "2", "age":"20"}'>홍길자</a></li>
        <li><a href="#" data-user-info='{"id": "3", "age":"30"}'>이순신</a></li>
        <li><a href="#" data-user-info='{"id": "4", "age":"4"}'>박찬호</a></li>
    </ul>

    결과: <div class="result"></div>

    <script>
        var list = document.querySelector(".list");
        list.onclick = function() {

            //1.
            event.preventDefault();

            //2.
            if(event.target.tagName != "A") return;

            //3. data - 으로 만들어진 속성은 태그에서 찾아 쓸 수 있어요~
            // console.dir(event.target);
            // console.dir(event.target.dataset);
            // console.dir(event.target.dataset.userInfo);

            var data = event.target.dataset.userInfo;

            var result = JSON.parse(data); //key, value값 ""로 묶어야 에러 안남
            console.log(result);
        }

    </script>
</body>
</html>

 

Document
  • 메뉴1
  • 메뉴2
  • 메뉴3
<!DOCTYPE html>
<html lang="en">
<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>

    <style>
        .toggle li {    
            display: inline-block;
            padding: 15px 20px 14px;
            width: 25%; 
            text-align: center;
            border: 1px solid #333;
            cursor: pointer;
        }

        .toggle-menu {display: none;}
        .active { display: block; animation: fadeIn 1s ease-in-out;} /* active가 옮겨지면서 내용이 보여지고, 안보여짐 */

        /* 애니메이션 라이브러리 사이트: https://michalsnik.github.io/aos/, https://whirl.netlify.app/ */
        /* 애니메이션 */
        @keyframes fadeIn {
            from { /* from에서 to로 바꾸겠다 */
                opacity: 0;
                background-color: aquamarine;
                margin-left: -100px;
            } to {
                opacity: 1;
                background-color: beige;
                margin-left: 0;
            }
        }
    </style>

</head>
<body>

    <!--
        1. ul에 이벤트 버블링을 이용해서 클릭이벤트를 걸고 클릭되는 타겟의 data-id를 얻습니다.
        2. toggle-menu의 active속성을 삭제
        3. data-id의 값에 알맞는 태그에 active속성을 추가하면됩니다.
    -->

    <section>

        <ul class="toggle">
            <li data-id="#toggle1">메뉴1</li>
            <li data-id="#toggle2">메뉴2</li>
            <li data-id="#toggle3">메뉴3</li>
        </ul>

        <div class="menu">
            <div class="toggle-menu active" id="toggle1">
                토글메뉴1
            </div>
            <div class="toggle-menu" id="toggle2">
                토글메뉴2
            </div>
            <div class="toggle-menu" id="toggle3">
                토글메뉴3
            </div>
        </div>

    </section>

    <script>
        var toggle = document.querySelector(".toggle"); //ul 가져옴, 부모태그 가져옴
        var menu = document.querySelector(".menu"); //토글메뉴 3개 다 나옴

        toggle.onclick = function() {
            var active = document.querySelector(".active");
            var click = document.querySelector(event.target.dataset.id); //누른 버튼의 id가져와서 변수에 담음
            
            // console.log(event.target); //target은 각각의 li임
            // console.log(event.target.dataset.id); //각각의 data-id 나옴

            if(event.target.tagName != "LI") return; //li일때만 동작하게끔

            console.log(active);
            active.classList.remove("active");

            console.log(click);
            click.classList.add("active");

            //if 아래 다른 풀이
            var trigger = event.target.dataset.id;
            var tag = document.querySelector(trigger); //id를 가지고 있는 태그

            //다른 태그는 active 삭제, 반복문으로 돌려서 삭제
            var menu = document.querySelectorAll(".toggle-menu");
            for(var i = 0; i < menu.length; i++) {
                menu[i].classList.remove("active");
            }

            tag.classList.add("active"); //active 추가
        }
    </script>

    
</body>
</html>

애니메이션 추가

@keyframes

애니메이션 사용방법

 <style>
 .active { display: block; animation: fadeIn 1s ease-in-out;} /* active가 옮겨지면서 내용이 보여지고, 안보여짐 */

/* 애니메이션 */
@keyframes fadeIn {
	from { /* from에서 to로 바꾸겠다 */
		opacity: 0;
		background-color: aquamarine;
		margin-left: -100px;
	} to {
		opacity: 1;
		background-color: beige;
		margin-left: 0;
	}
}
 </style>

fadeIn

 

애니메이션 라이브러리 사이트

 

AOS - Animate on scroll library

AOS Animate On Scroll Library Scroll down

michalsnik.github.io

 

Whirl: CSS loading animations with minimal effort!

You need to enable JavaScript to run this app. WhirlCSS loading animations with minimal effort!

whirl.netlify.app


오늘 하루

더보기

기억에 남는 부분

 

어려운 부분

 

문제 해결 부분

 

728x90
profile

원지의 개발

@원지다

250x250