본문 바로가기
03. 웹 표준 기술/jQuery

[jQuery] 04. dom_dynamic

by moca7 2024. 8. 21.

 

 

ㅁ 동적으로 요소를 생성하거나 복제, 제거한다

 

 

 

ㅁ < 동적으로 요소 생성 >

 

 

(1) 문자열로 요소 만드는 방식

- 변수 = '<b>안녕하세요</b>'            //     이렇게 만들고 변수에 담을 수 있다는 뜻.

 

 

(2) jQuery 객체로 요소 만드는 방식

- 변수 = $('<b></b>').text('안녕하세요');     

- 변수 = $('<b>안녕하세요</b>');                //  더 간단한 방법 ( b태그 요소 객체가 만들어짐)

 

 

- jQuery 객체로 요소를 만들면 jQuery 메소드를 사용할 수 있다.

문자열을 달러 괄호로 감싸면 된다.

- 이때까지 달러 괄호 안에 요소 선택을 위해 선택자를 써왔는데, 항상 선택자를 써야하는 것은 아니다.

요소를 생성할 때는 문자열을 쓴다.

- 어떤 태그의 요소를 만들고 싶은지 그 태그를 작성해야 한다.

 

 

 

 

 

ㅁ < 동적으로 만들어진 요소를 특정 영역에 추가 >

 

 

(1) 문자열로 만들어진 요소를 추가

 

    요소.html('문자열로생성한요소');

 

 

(2) jQuery 객체로 만들어진 요소를 추가

- 아래의 두 방법 중 편한 방식을 택해서 쓰면 된다.

- jQuery 객체가 동적으로 만들어진 요소 객체다.

이렇게 만든 객체를 어떤 요소 내에 추가를 할건지 요소를 제시한다.

 

 

- jQuery객체.appendTo(요소)           :  요소 내에 마지막 자손으로 jQuery 객체가 추가된다.

- jQuery객체.prependTo(요소)          :  요소 내에 첫번째 자손으로 jQuery 객체가 추가된다.

- jQuery객체.insertBefore(요소)      요소의 앞에 이전 형제로 추가 (동등 레벨)

- jQuery객체.insertAfter(요소)          :  요소의 뒤에 다음 형제로 추가

 

 

- 요소.append(jQuery객체)             요소 내에 마지막 자손으로 jQuery 객체가 추가된다.

- 요소.prepend(jQuery객체)            요소 내에 첫번째 자손으로 jQuery 객체가 추가된다.

- 요소.before(jQuery객체)               요소의 앞에 이전 형제로 추가

- 요소.after(jQuery객체)                  요소의 뒤에 다음 형제로 추가

 

 

 

 

 
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>

    <!-- (1) 파일 다운받아서 연결하는 방법
    <script src="../assets/assets/lib/jquery-3.7.1.min.js"></script> -->

    <!-- (2) CDN 방식으로 연결하는 방법 -->

    <style>
        .added {
            color : palegreen;
        }
    </style>

</head>
<body>

    <h2>요소생성</h2>



    <h1 id="test1">
        <span>A</span>
    </h1>

    <h1 id="test2">
        <span>A</span>
    </h1>

    <h1 id="test3">
        <span>A</span>
    </h1>

    <h1 id="test4">
        <span>A</span>
    </h1>


    <script>

    </script>


   
</body>
</html>
 

 

- 기본세팅. h1 요소 내에 span 요소가 자손으로 있다.

h1 요소 내에 또다른 span 요소를 추가해 볼 예정이다.

그리고 동적으로 만들어진 요소에 '.added'라는 클래스를 부여해서 글씨 색깔을 바꿀 예정이다.

 

 

 

 
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>

    <!-- (1) 파일 다운받아서 연결하는 방법
    <script src="../assets/assets/lib/jquery-3.7.1.min.js"></script> -->

    <!-- (2) CDN 방식으로 연결하는 방법 -->

    <style>
        .added {
            color : palegreen;
        }
    </style>

</head>
<body>

    <h2>요소생성</h2>



    <h1 id="test1">
        <span>A</span>
    </h1>

    <h1 id="test2">
        <span>A</span>
    </h1>

    <h1 id="test3">
        <span>A</span>
    </h1>

    <h1 id="test4">
        <span>A</span>
    </h1>


    <script>

        $(document).ready(function() {
 
            $('<span class="added">B</span>').appendTo('#test1');

        })

    </script>

 
</body>
</html>
 

 

 

 

- span 요소를 jQuery 객체로 만들고, id가 test1인 h1 요소 내마지막 자손으로 추가했다.

- span은 인라인 요소다. div는 블럭 요소. 

블럭요소는 전체 가로 너비 차지. 인라인 요소는 내용의 크기만큼 너비 차지.

 

 

 

 

 
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>

    <!-- (1) 파일 다운받아서 연결하는 방법
    <script src="../assets/assets/lib/jquery-3.7.1.min.js"></script> -->

    <!-- (2) CDN 방식으로 연결하는 방법 -->

    <style>
        .added {
            color : palegreen;
        }
    </style>

</head>
<body>

    <h2>요소생성</h2>



    <h1 id="test1">
        <span>A</span>
    </h1>

    <h1 id="test2">
        <span>A</span>
    </h1>

    <h1 id="test3">
        <span>A</span>
    </h1>

    <h1 id="test4">
        <span>A</span>
    </h1>


    <script>

        $(document).ready(function() {
 
            $('<span class="added">B</span>').appendTo('#test1');
            $('<span class="added">B</span>').prependTo('#test2');   
            $('<span class="added">B</span>').insertBefore('#test3'); 
            $('<span class="added">B</span>').insertAfter('#test4');

        })

    </script>

   
</body>
</html>
 
 

 

- B가 작게보여진다. h1 요소 내에 추가된 게아니고. h1과 동위선상으로 이전/이후 위치에 추가되었기 때문에 글씨 크기는 크지 않다. h1 요소 내에 있지 않기 때문이다.

 

 

 

 

ㅁ jQuery와 요소의 위치를 바꿔본다. (다른 메소드 사용)

 

 
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>

    <!-- (1) 파일 다운받아서 연결하는 방법
    <script src="../assets/assets/lib/jquery-3.7.1.min.js"></script> -->

    <!-- (2) CDN 방식으로 연결하는 방법 -->

    <style>
        .added {
            color : palegreen;
        }
    </style>

</head>
<body>

    <h2>요소생성</h2>



    <h1 id="test1">
        <span>A</span>
    </h1>

    <h1 id="test2">
        <span>A</span>
    </h1>

    <h1 id="test3">
        <span>A</span>
    </h1>

    <h1 id="test4">
        <span>A</span>
    </h1>


    <script>

        $(document).ready(function() {
 
            /*
            $('<span class="added">B</span>').appendTo('#test1');
            $('<span class="added">B</span>').prependTo('#test2'); 
            $('<span class="added">B</span>').insertBefore('#test3'); 
            $('<span class="added">B</span>').insertAfter('#test4');
            */

            $('#test1').append($('<span class="added">B</span>'));
            $('#test2').prepend($('<span class="added">B</span>'));
            $('#test3').before($('<span class="added">B</span>'));
            $('#test4').after($('<span class="added">B</span>'));

        })

    </script>


   
</body>
</html>
 

 

 

- 방금 전과 실행 결과는 동일하다.

 

 

 

 

 

 

ㅁ < 요소 복제 >

 

 
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>

    <!-- (1) 파일 다운받아서 연결하는 방법
    <script src="../assets/assets/lib/jquery-3.7.1.min.js"></script> -->

    <!-- (2) CDN 방식으로 연결하는 방법 -->

    <style>
        .item {
            background-color: blueviolet;
            width: 100px;
            height: 100px;
            text-align: center;
            line-height: 100px;
            margin: 10px;
            font-size: 25px;
            color: white;
            font-weight: 900;
        }
    </style>

</head>
<body>


    <h2>요소 복제</h2>

    <div id="clone-test">

        <div id="item1" class="item">    <!-- 복제할 요소 -->
            <span>안녕</span>
        </div>

    </div>


    <button id="clone-btn">복제</button>
 

    <!-- 복제한 요소를 붙여넣기 할 영역 -->
    <div id="clone-result"></div>



    <script>


    </script>


   
</body>
</html>
 

 

 

- 기본 세팅

- 문구를 수직정렬하고 싶다면 line-height를 height 값과 동일하게 주면 된다. 

 

 

 

 

 

ㅁ < 요소 객체 복제 메소드 >

 

 

    요소.clone( [true|false] )    :    해당 요소를 복제해서 반환

 

true      :  복제할 요소의 이벤트도 같이 복사

false    :  복제할 요소의 이벤트는 복사 안 함      (기본값)

 

 

 

 

 
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>

    <!-- (1) 파일 다운받아서 연결하는 방법
    <script src="../assets/assets/lib/jquery-3.7.1.min.js"></script> -->

    <!-- (2) CDN 방식으로 연결하는 방법 -->

    <style>
        .item {
            background-color: blueviolet;
            width: 100px;
            height: 100px;
            text-align: center;
            line-height: 100px;
            margin: 10px;
            font-size: 25px;
            color: white;
            font-weight: 900;
        }
    </style>

</head>
<body>


    <h2>요소 복제</h2>

    <div id="clone-test">

        <div id="item1" class="item">    <!-- 복제할 요소 -->
            <span>안녕</span>
        </div>

    </div>


    <button id="clone-btn">복제</button>
 

    <!-- 복제한 요소를 붙여넣기 할 영역 -->
    <div id="clone-result"></div>
 



    <script>

        $(function() {

            // 이벤트도 복제되는지 확인 위해 복제할 요소에 이벤트 부여하기
            $('.item').hover(function(){              // 두 function 제시. 첫번째는 mouseenter시, 두번째는 mouseout시.

                $(this).css('backgroundColor', 'pink');

            }, function(){

                $(this).css('backgroundColor', 'green');

            })



            // 복제 버튼 실행시 실행되게
            $('#clone-btn').on('click', function() {

                // id가 item1인 요소를 복제해서 #clone-result에 자손으로 추가할 것이다.
                $('#clone-result').append($('#item1'));
                // 그런데 이렇게 하면 기존 요소는 사라짐. 아예 이동되어버린다.

            })



        })

    </script>


   
</body>
</html>
 

 

- 복제할 요소에 이벤트 부여했다. 

'안녕' 요소의 배경색이 보라색이었다가 마우스가 진입하면 분홍, 나오면 초록색이 된다.

- 그런데 이렇게 하면 기존 요소는 사라짐. 아예 이동되어버린다.

- 그냥 요소만 제시하면 이동이 되어버린다.

 

 

 

 
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>

    <!-- (1) 파일 다운받아서 연결하는 방법
    <script src="../assets/assets/lib/jquery-3.7.1.min.js"></script> -->

    <!-- (2) CDN 방식으로 연결하는 방법 -->

    <style>
        .item {
            background-color: blueviolet;
            width: 100px;
            height: 100px;
            text-align: center;
            line-height: 100px;
            margin: 10px;
            font-size: 25px;
            color: white;
            font-weight: 900;
        }
    </style>

</head>
<body>


    <h2>요소 복제</h2>

    <div id="clone-test">

        <div id="item1" class="item">    <!-- 복제할 요소 -->
            <span>안녕</span>
        </div>

    </div>


    <button id="clone-btn">복제</button>
 

    <!-- 복제한 요소를 붙여넣기 할 영역 -->
    <div id="clone-result"></div>



    <script>

        $(function() {

            // 복제할 요소에 이벤트 부여하기
            $('.item').hover(function(){

                $(this).css('backgroundColor', 'pink');

            }, function(){

                $(this).css('backgroundColor', 'green');

            })



            // 복제 버튼 실행시 실행되게
            $('#clone-btn').on('click', function() {

                // id가 item1인 요소를 복제해서 #clone-result에 자손으로 추가

                // $('#clone-result').append($('#item1'));
                // 그런데 이렇게 하면 기존 요소는 사라짐. 아예 이동되어버린다.

                $('#clone-result').append($('#item1').clone());       // 복붙은 됐으나 이벤트는 복사 안 됨.
                $('#clone-result').append($('#item1').clone(true));   // 이벤트까지 복사되었다.


            })



        })

    </script>


   
</body>
</html>
 

 

- 복제된 요소를 지금은 바로 append로 추가하고 있지만 변수에 기록을 해놨다가 활용해도 된다.

 

 

 

 

 

 

 

ㅁ < 하위 요소 제거 메소드 >

 

- 요소.empty()    :  해당 요소의 하위 요소들 제거

 

 

 

ㅁ < 선택 요소 제거 및 잘라내기 메소드 >

 

- 둘 다 호출만으로 선택된 요소가 제거된다.

제거할 뿐만 아니라 제거된 요소 자체를 반환해준다.( =이게 잘라내기 기능이다)

 

- 요소.remove()    해당 요소 제거 후 반환 (이벤트는 같이 반환 안됨)

- 요소.detach()    :  해당 요소 제거 후 반환 (이벤트도 같이 반환)

 

 

 

 

 

 

ㅁ < 요소 제거 및 잘라내기 >

 

 

 
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>

    <!-- (1) 파일 다운받아서 연결하는 방법
    <script src="../assets/assets/lib/jquery-3.7.1.min.js"></script> -->

    <!-- (2) CDN 방식으로 연결하는 방법 -->

    <style>
        .item {
            background-color: blueviolet;
            width: 100px;
            height: 100px;
            text-align: center;
            line-height: 100px;
            margin: 10px;
            font-size: 25px;
            color: white;
            font-weight: 900;
        }
    </style>

</head>
<body>


    <h2>요소 제거 및 잘라내기</h2>

    <div id="remove-test">

        <div id="item2" class="item">    <!-- 제거할 요소 -->
            <span>안녕</span>
        </div>

    </div>


    <button id="empty-btn">제거</button>
    <button id="remove-btn">잘라내기1</button>
    <button id="detach-btn">잘라내기2</button>
 

    <!-- 잘라낸 요소를 붙여넣기 할 영역 -->
    <div id="remove-result"></div>




    <script>

        $(function() {

            // 제거할 요소에 이벤트 부여하기 (이전거 그대로 재탕. 제거할 요소에도 이벤트가 연결되어있다.)
            $('.item').hover(function(){

                $(this).css('backgroundColor', 'pink');

            }, function(){

                $(this).css('backgroundColor', 'green');

            })


        })

    </script>


   
</body>
</html>
 

 

- 기본 세팅. 

- hover 이벤트도 그대로다.

 

 

 

 

 

 
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>

    <!-- (1) 파일 다운받아서 연결하는 방법
    <script src="../assets/assets/lib/jquery-3.7.1.min.js"></script> -->

    <!-- (2) CDN 방식으로 연결하는 방법 -->

    <style>
        .item {
            background-color: blueviolet;
            width: 100px;
            height: 100px;
            text-align: center;
            line-height: 100px;
            margin: 10px;
            font-size: 25px;
            color: white;
            font-weight: 900;
        }
    </style>

</head>
<body>


    <h2>요소 제거 및 잘라내기</h2>

    <div id="remove-test">

        <div id="item2" class="item">    <!-- 제거할 요소 -->
            <span>안녕</span>
        </div>

    </div>


    <button id="empty-btn">제거</button>
    <button id="remove-btn">잘라내기1</button>
    <button id="detach-btn">잘라내기2</button>

    <!-- 잘라낸 요소를 붙여넣기 할 영역 -->
    <div id="remove-result"></div>




    <script>

        $(function() {

            // 제거할 요소에 이벤트 부여하기 (이전거 그대로 재탕. 제거할 요소에도 이벤트가 연결되어있다.)
            $('.item').hover(function(){

                $(this).css('backgroundColor', 'pink');

            }, function(){

                $(this).css('backgroundColor', 'green');

            })
 


            $('#empty-btn').on('click', function() {

                // $('#item2').empty(); 이거는 버튼 누르면 박스 자체가 사라지는게 아니고 '안녕' 텍스트만 사라짐.
                $('#remove-test').empty();

            })
 

            $('#remove-btn').on('click', function() {

                // $('#item2').remove(); 이렇게만 쓰면 버튼을 누르는 순간 박스 자체가 사라지고 끝.
                const removeEl = $('#item2').remove();
                $('#remove-result').append(removeEl); // 붙여넣기 되었으나 이벤트는 없다.

            })
 

            $('#detach-btn').on('click', function() {

                // $('#item2').detach();
                const detachEl = $('#item2').detach();
                $('#remove-result').append(detachEl);  //  이벤트도 이동되었다.

            })


        })

    </script>


   
</body>
</html>
 

 

처음 상태 - '제거'

 

처음 상태 - '잘라내기1'

 

처음 상태 - '잘라내기2'

 

 

- remove()와 detach()는 제거된 요소 자체를 반환하기 때문에 변수에 담아뒀다가 어딘가에 출력도 가능하다.

 

 

 

 

 

ㅁ 연습문제. 

 

문제1. 

#create-btn 버튼 클릭시 위의 객체배열의 값으로 테이블 요소를 생성해서 #result 영역에 출력하기.

이때 3행 3열짜리 테이블로 만든다.

 

첫번째 열에는 상품명, 두번째 열에는 상품 가격, 세번째 열에는 해당 상품에 대한 정보를 볼 수 있는 '확인' 버튼 두기.

(이게 제목행에 들어갈 내용은 아님. 제목행 없음)

 

'확인' 버튼을 클릭하면 alert로 각각의 행의 상품명 : name, 상품가격 : 30000 나오게끔.

 

 

문제2.

동적으로 만들어진 테이블 요소 내의 각 행별 마지막 셀에 있는 버튼 클릭시 해당 행의 상품정보(상품명, 상품가격)를 alert로 띄워주기.

 

 

 

 
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>

    <!-- (1) 파일 다운받아서 연결하는 방법
    <script src="../assets/assets/lib/jquery-3.7.1.min.js"></script> -->

    <!-- (2) CDN 방식으로 연결하는 방법 -->


</head>
<body>

    <h2>연습</h2>

    <button id="create-btn">요소 생성</button>
    <br><br>

    <div id="result"></div>



    <script>

        $(document).ready(function() {

            const productList = [       //   세 개의 상품 객체가 있는 배열
                {
                    name : '마우스',
                    price : 10000
                },
                {
                    name : '키보드',
                    price : 20000
                },
                {
                    name : '마이크',
                    price : 30000
                }
            ];

        })
       

    </script>


   
</body>
</html>
 

- 동적으로 요소를 만들어서 어딘가에 출력하고자 한다면 그 영역을 선택할 수 있게끔 적어도 요소 하나는 있어야만 한다.

아이디가 result인 div 요소 하나를 생성한다. 그리고 여기에 동적으로 생성된 요소를 추가한다.

- 페이지 로드 시에는 아무것도 없지만 버튼을 누르는 순간 요소를 동적으로 만들어서 #result에 자손으로 추가한다. 

 

 


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>

    <!-- (1) 파일 다운받아서 연결하는 방법
    <script src="../assets/assets/lib/jquery-3.7.1.min.js"></script> -->

    <!-- (2) CDN 방식으로 연결하는 방법 -->

</head>
<body>

    <h2>연습</h2>

    <button id="create-btn">요소 생성</button>
    <br><br>

    <div id="result"></div>



    <script>
      $(document).ready(function() {
 
        const productList = [
          {
            name: '마우스',
            price: 10000
          },
          {
            name: '키보드',
            price: 20000
          },
          {
            name: '마이크',
            price: 30000
          }
        ];
 
 
 
        $('#create-btn').on('click', function() {
 
          let tableEl = '<table border="1">';
          for(let product of productList){
            tableEl += '<tr>'
                      + '<td>' + product.name + '</td>'
                      + '<td>' + product.price + '</td>'
                      + '<td><button>확인</button></td>'
                     + '</tr>';
          }
          tableEl += '</table>';
 
          $('#result').html(tableEl);
        })
 
 
 

        // $('#result button') 이렇게 하면 안 됨. 페이지 로드 시에는 버튼이 없다.
        $('#result').on('click', 'button', function() {            //     하위 요소에 이벤트 걸기
          // $(this) : 현재 이벤트가 발생한 클릭된 확인 버튼
          // $(this).parent().prev().prev() : 현재 클릭된 확인 버튼 행의 첫번째 셀
          // $(this).parent().prev() : 현재 클릭된 확인 버튼 행의 두번째 셀
       
          alert('상품명: ' + $(this).parent().prev().prev().text()
             + ', 상품가격: ' + $(this).parent().prev().text());
        })

 
      })
    </script>
   
</body>
</html>
 

 

- button이 td 안에 있기 대문에 parent().prev().prev()다. 

- 문제2처럼 할 때가 굉장히 많다.

동적으로 요소가 만들어지고 그 만들어진 행에 각각의 버튼에 이벤트를 연결해야할 때가 많다.

사이트의 댓글 기능. 댓글을 작성하는 순간 하단에 내가 작성한 댓글이 보여진다. 이게 동적으로 만들어진 요소다.

- 그 행에 댓글 수정버튼, 삭제버튼이 있는데 그런게 다 동적으로 만들어진 요소라서 거기에 이벤트를 연결하고자 한다면 문제1처럼 매개변수 3개짜리 on 메소드를 사용.

그리고 그때 각각 클릭시 현재 이벤트가 발생한 요소로부터 탐색해야될 때 문제2처럼 쓰고.(parent().prev().prev())

 

- this를 쓸 수 있는 이유는 익명함수이기 때문.

화살표함수를 쓸 때는 이벤트 객체를 매개변수로 전달받아서 evt.target으로 사용해야한다.

 

 

 

ㅁ 짤막 문제 - 자바스크립트 구문을 jQuery식으로 바꾸기