ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • jQuery 클릭이벤트 다루기 (this, parent, closest)
    Web/jQuery 2018. 9. 5. 11:03

    버튼을 클릭했을 때 p태그가 나타나도록 하기 이전 포스팅과 같은 html파일이고 모두 같은 button 태그로 등록되어 있다.

    이 버튼들을 클릭했을 때 가격을 보여주고 싶다면 해당 태그들에 클릭이벤트를 주면 된다. 다음의 코드처럼 말이다.

    ※모든 예제는 아톰(atom)으로 작성했고, 오페라 브라우저를 통해 확인했다. html 문서 작업이 굉장히 편하기 때문에 사용을 권하고, 브라우저는 크롬이나 오페라를 권장한다. 인터넷 익스플로러에서는 같은 결과가 나오지 않는 경우가 굉장히 많을 것이다. ( 브라우저들의 DOM 작성 방법이 표준화되지 않았기 때문)

    <!DOCTYPE html>
    <html>
      <head>
        <link rel="stylesheet" type="text/css" href="./layout.css" />
        <title>Vacation Packages</title>
        <script type="text/javascript" src="./jquery-3.1.1.min.js"></script>
        <script type="text/javascript">
    
            var price = $("<p id='price'>from $399.99</p>"); // 매개변수에 해당하는 Element가 만들어진다.
    
            $("button").click(function(){ 
             // 모든 button 객체를 대상으로 클릭 이벤트가 발생한다면
             // 콜백 함수(function)를 실행하도록 한다.
    
              $("button").remove(); // 버튼들을 지우고
              $(".vacation").append(price); // vacation 클래스 내부의 가장 마지막 부분에 price를 붙인다.
            });
          });
          
    
        </script>
      </head>
      <body>
        <fieldset>
          <legend>Vacations</legend>
          <h1>Vacation Packages</h1>
          <h3>jQuery Travels</h3>
          <ul>
            <li class='vacation'>
              <h2>Hawaiian Vacation</h2>
              <p>Comments on this deal:</p>
              <ul class="comments">
                <li>"Amazing Deal!"</li>
                <li>"Can't wait to take this trip!"</li>
              </ul>
              <button>GET PRICE</button>
            </li>
          </ul>
          <p class="call">Call us at 1-555-jquery-air to make a reservation today!</p>
        </fieldset>
      </body>
    </html>
    
    

    클릭이벤트를 제어하는 기본 방식이다. 여기서 button 태그는 DOM으로써 브라우저가 최초 보여줄 때 생성되는 Element(이하 엘레먼트)이다. 이와 달리 자바스크립트 내에서 객체화 시키는 Element들을 Shadow DOM이라 한다. 
     html 문서의 body 부분에 있는 태그들을 DOM으로, script태그에서 $()를 통해 생성되는 엘레먼트들을 Shadow DOM으로 이해하면 되겠다. 이들은 이벤트를 동작시키는 방식이 다르다. 해당 포스팅에서는 DOM 엘레먼트의 처리방식에 대해 포스팅.
    다음의 jQuery 코드는 button태그에 이벤트를 걸어야 한다. button 태그는 body에 있는 태그이므로 DOM이고, 위 코드와 같이 click 키워드를 사용해 클릭 이벤트를 제어한다. $()로 객체화된 모든 button 태그들에 click이 발생하면 안의 콜백함수(function) 가 호출되어 이후를 제어한다는 의미이다.
    버튼들을 remove() 함수를 통해 지우고 해당 태그의 하위 마지막 부분에 price 엘레먼트를 생성해 붙이는 방식으로 값을 보여준다. remove에 대해 첨언하자면 지우는 함수 중 사용 빈도가 가장 높은 것으로 생각하면 되겠다. hide()와 detach() 함수를 통해서도 브라우저에서 같은 효과를 나타낼 수 있다. 하지만 hide는 말 그대로 가리기만 하고 html 코드를 확인해보면 style이 hidden으로 지정되어 있다. detach()는 태그만 지우고 DOM은 남기는 것이고, remove()는 DOM까지 함께 지우는 것이라고 하는데 정확한 차이점은 파악할 필요성이 낮으며 remove를 주로 사용한다고 여기고 넘어가도록 하자.

    결과를 확인해보면

    다음과 같이 모든 버튼이 없어진다.

    하지만 보통 클릭하는 버튼만 정확하게 변경해야 하는 경우가 잦고 이를 위해 제공하는 함수가 parent()이다






    <!DOCTYPE html>
    <html>
      <head>
        <link rel="stylesheet" type="text/css" href="./layout.css" />
        <title>Vacation Packages</title>
        <script type="text/javascript" src="./jquery-3.1.1.min.js"></script>
        <script type="text/javascript">
    
        $(document).ready(function(){ // document 생략 가능하다.
            $("button").click(function(){
              var amount = $(this).parent().data("price");
    
              var price = $("<p>from $" + amount + "</p>");
             
              $(this).parent().append(price);
              //$(this).closest(".vacation").append(price);
              $(this).remove(); //선택한 button을 지워라
            });
          });
        </script>
      </head>
      <body>
        <fieldset>
          <legend>Vacations</legend>
          <h1>Vacation Packages</h1>
          <h3>jQuery Travels</h3>
          <div id="vacations">
            <ul>
              <li class='vacation' data-price="499.99">
                <h2>Hawaiian Vacation</h2>
                <p>Comments on this deal:</p>
                <ul class="comments">
                  <li>"Amazing Deal!"</li>
                  <li>"Can't wait to take this trip!"</li>
                </ul>
                <button>GET PRICE</button>
              </li>
            </ul>
            <ul>
              <li class='vacation' data-price="599.99">
                <h2>Olando</h2>
                <p>Comments on this deal:</p>
                <ul class="comments">
                  <li>There aren't any comments on this deal yet.</li>
                </ul>
                <div>
                <button>GET PRICE</button>
                </div>
              </li>
            </ul>
            <ul>
              <li class='vacation' data-price="299.99">
                <h2>Visit Japan</h2>
                <p>Comments on this deal:</p>
                <ul class="comments">
                  <li>"Never been, but can't wait!</li>
                  <li> </li>
                </ul>
                <button>GET PRICE</button>
              </li>
            </ul>
          </div>
          <p class="call">Call us at 555-2593 to make a reservation today!</p>
        </fieldset>
      </body>
    </html>
    
    

    다음과 같이 this와 parent() 함수를 써서 태그를 제어한다.

    this : jQuery에서 this는 자바와 비슷하게 해당 키워드를 호출한 호출자를 가리키도록 한다. 코드에서는 button 엘레먼트에 이벤트를 등록했고, 같은 Element가 여러개 존재하더라도 자신이 호출된 버튼에 대한 정보를 가지고 있기 때문에 구별이 가능하다. 

    parent() : 엘레먼트의 바로 상위 엘레먼트를 나타내는 함수. html 파일에서는 button의 상위 엘레먼트인 li 엘레먼트를 가리키게 된다.

    data() : 태그에 부가할 수 있는 속성. html5부터 제공되는 강력한 기능이다. vacation 클래스 태그들에 'data-속성명'의 형태로 입력하면 그 값을 data(속성명) 으로 가져올 수 있는 것이다.

    다음의 함수들에 대해 파악했다면 코드 분석이 가능하다.
    button이 눌렸을 때 해당 button의 바로 상위 단계 엘레먼트에 parent() 함수를 통해 접근한다. li 엘레먼트에는 data-price가 속성으로 지정되어 있고, data("price")함수를 통해 그 값을 가져와 amount에 저장한다. 이후 price 변수에 p태그와 amount값을 합친 태그를 $ 통해 Element화 시킨 후 해당 버튼을 지우고 price 엘레먼트를 추가해 화면을 바꾼다. 그 결과

    지역별로 다른 가격이 출력된다.

    하지만 여기에는 치명적인 결함이 있다. 바로 html 코드 구조이다.

    해당 코드에 대해 마우스 오른쪽 버튼으로 요소 검사 수행하면(요소 검사는 크롬이나 오페라 브라우저를 꼭 사용해야 한다. 다른 브라우저로는 확인 불가) 엘레먼트 창에 다음과 같이 코드가 나온다. append함수를 통해 추가한 p 엘레먼트의 위치를 보자.
     두번째 p 엘레먼트는 div 엘레먼트의 하위에 있다. 이는 코드에서 parent() 함수를 통해 바로 상위 엘레먼트를 호출하도록 작성했기 때문이다. div 엘레먼트에 다른 엘레먼트를 추가했다면, p엘레먼트는 그 엘레먼트 아래에 들어가 p 엘레먼트의 구조가 다르게 될 우려가 있다. 따라서 엘레먼트위치를 항상 상위 특정한 엘레먼트의 하위에 올 수 있도록 해주는 것이 필요하다. 이를 돕는 키워드가 closest()이다.

    소스코드에서
    $(this).parent().append(price); 를 주석처리하고 아래 주석인
    $(this).closest(".vacation").append(price); 의 주석을 지워 수행시키도록 한다. closest의 매개변수로는 내가 지정하고 싶은 Selector를 넣는다.

    수행 결과

    두번째 박스에서 p 엘레먼트가 li 엘레먼트의 맨 뒤로 붙게 된다. 구조적으로 일관성 있게 맞춰준 것이다


Designed by Tistory.