07. JavaScript - DOM(Document Object Model)

박지윤·2023년 9월 5일
0

JavaScript

목록 보기
7/13

DOM (Document Object Model)

1. DOM이란?

웹 문서의 모든 요소를 자바스크립트를 이용해 조작할 수 있도록 하는 것을 말한다. 이 DOM은 다음과 같은 계층 구조로 표현된다.

위 그림을 예로 html, head, body, title 등 네모 상자에 들어 있는 것들을 노드 라고 부르고 그 노드들을 연결하는 선들을 가지 라고 부른다.

웹문서의 태그는 요소 노드
태그가 품고 있는 텍스트는 요소 노드의 자식 노드인 텍스트 노드
태그의 속성은 요소 노드의 자식 노드 인 속성 노드
주석은 주석 노드

이 DOM을 통해 다음과 같은 작업을 수행할 수 있다.

  • 새로운 HTML 요소나 속성 추가
  • 기존의 HTML 요소나 속성 제거
  • HTML 문서 내의 모든 HTML 요소 변경
  • HTML 문서 내의 모든 THML 속성 변경
  • HTML 문서 내의 모든 CSS 변경
  • HTML 문서에 새로운 HTML 이벤트 및 이벤트 반응 추가

2. DOM 요소 선택

DOM 요소를 선택하는 방법에는 6가지가 있다.

document.getElementById

document.getElementById("아이디")는 HTML에 부여한 id 속성으로 DOM 요소를 선택하는 방법이다.
한 문서에 id는 유일한 값이기 때문에, elements가 아닌 element로 작성한다.

이 방법은 id 값으로 축약해 작성할 수도 있어, 자주 사용된다.

<body>
  <h1 id = "title">This is Title</h1>
  <button id="btn">blue</button>
  <button><button>
  <script>
    document.getElementById("title").style.color = "red";  // title이 빨간 색으로 변경
    btn.onclick = function(){     // id가 btn인 버튼을 누르면 title이 파란색으로 변경
      title.style.color = "blue"  // 다른 버튼은 눌러도 title의 색이 변경되지 않음
    }
    
    //document.getElementsById("title").style.color = "red"와 title.style.color = "red"는 동일함 
  </script>
</body>

document.getElementsByTagName

document.getElementsByTagName("태그이름")는 해당 태그 이름의 요소들을 선택하는 방법이다. 하나의 특정한 요소를 선택하기 위해서는 중괄호 뒤에 인덱스를 추가해주어야 한다.

 <!-- 여름의 배경색을 파란색으로 변경-->
<body>
  <ul>
    <li></li>
    <li>여름</li>
    <li>가을</li>  
    <li>겨울</li>
  </ul>
  <script>
    document.getElementsByTagName("li")[1].style.backgroundColor = "blue";
  </script>
</body>

document.getElementsByClassName

document.getElementsByTagName("클래스이름")는 해당 클래스에 속한 요소들을 선택하는 방법이다. 하나의 특정한 요소를 선택하기 위해서는 중괄호 뒤에 인덱스를 추가해주어야 한다.

 <!-- class = "red"  맨 첫번째 요소에만 텍스트 컬러 빨강, 
      class = "blue" 모든 요소에 텍스트 컬러 파랑 -->
<body>
  <ul>
    <li class="red"></li>
    <li class="blue">여름</li>
    <li class="red">가을</li>  
    <li class="blue">겨울</li>
  </ul>
  <script>
    document.getElementsByClassName("red")[0].style.color = "red";
    document.getElementsByClassName("blue").style.color = "blue";
  </script>
</body>

document.getElementsByName

document.getElementsByName("name")은 해당 name 속성값을 가진 요소를 선택하는 방법이다. 하나의 특정한 요소를 선택하기 위해서는 중괄호 뒤에 인덱스를 추가해주어야 한다.

 <!-- class = "red"  맨 첫번째 요소에만 텍스트 컬러 빨강, 
      class = "blue" 모든 요소에 텍스트 컬러 파랑 -->
<body>
  <div>
  	<img src ="#" alt="#" name="photo">
  </div>
  <script>
    document.getElementsByName("photo")[0].src = "#2";  // img src가 #에서 #2로 변경
  </script>
</body>

document.querySelector & document.querySelectorAll

document.querySelector(선택자)는 해당 선택자로 선택되는 요소를 선택하는 방법이다. ID가 아닌 클래스명이나 Tag를 통해 선택할 경우, 가장 위에 있는 요소를 선택한다.

다른 요소를 선택하거나, 모든 요소를 선택하고 싶다면 document.querySelectorAll(선택자)을 이용하면 된다.

  • Id : querySelector("#id")
  • Class: querySelector(".class")
  • Tag Name: querySelector("tagname")
<body>
  <ul>
    <li>HTML</li>
    <li class="active">CSS</li>
    <li>JavaScript</li>
  </ul>
  <ol>
    <li>HTML</li>
    <li class="active">CSS</li>
    <li>JavaScript</li>
  </ol>

  <script>
    // 최상위 요소의 li에 스타일 적용 (ul 태그의 첫번째 li에 적용 )
    var li = document.querySelector("li");
    li.style.color = "red"; 

    //querySelectorAll과 for문은 세트! for문이 없으면 다른 요소에 스타일이 적용되지 않음. 
    var lis = document.querySelectorAll(".active");  

    for(var i=0; i < lis.length; i++){
      lis[i].style.color = "blue";
    }

  </script>



2. HTML 요소의 생성

HTML 요소를 자바스크립트에서 생성하는 메소드에는 createElement()createTextNode(), appendChild(), setAttribute()가 있다.

  • createElement(태그 이름)는 지정한 태그 이름을 입력하면 해당 요소를 생성한다.
  • createTextNode(텍스트)는 지정한 텍스트를 가진 텍스트 노드를 생성한다.
  • appendChild(자식노드)는 부모 노드에 자식 노드를 추가한다.
  • setAttribute(속성, 속성값)는 노드에 속성을 추가 또는 변경한다.
// <p>안녕하세요</p> 생성하기 

var newP = document.createElement("p");  // p태그 추가
var newText = document.createTextNode("안녕하세요"); // 텍스트 노드 추가
newP.appendChild(newText)  // 텍스트 노드를 p태그의 자식 노드로 추가
document.body.appendChild(newP); // p태그를 body의 자식 노드로 추가 
newP.setAttribute("id", "subtitle");



3. HTML 이벤트 핸들러

이벤트란 브라우저에서 사용자의 조작이나 환경의 변화로 벌어진 사건을 말하고, 이러한 이벤트에 즉각적인 반응을 할 수 있게 하는 것을 핸들러라고 부른다.

브라우저에서 발생하는 이벤트에는 5가지가 있다.

이벤트이벤트 설명
윈도우 이벤트브라우저에 변화가 생겼을 때 발생하는 이벤트
마우스 이벤트사용자가 마우스로 조작했을 때 발생하는 이벤트
키보드 이벤트사용자가 키보드를 조작했을 때 발생하는 이벤트
폼 이벤트폼요소 조작에 의해 발생하는 이벤트
클립보드 이벤트사용자가 복사, 자르기, 붙여넣기를 할 때 발생하는 이벤트



이벤트 추가 방법

1) HTML 태그에 직접 넣기

첫 번째 방법은 HTML 태그에 직접 이벤트를 넣는 방법이다.

<!--버튼을 누르면 prompt창-->
<button onclick="prompt('나이를 입력하세요')">나이 입력</button> 
<!--p에 마우스를 올리면 빨간색, 빠지면 검정색-->
<p onmouseover= "style.color='red'" onmouseout="style.color='black'">안녕하세요</p> 

가장 간단한 방법이지만, HTML 코드에 자바스크립트 코드가 추가되어 가독성이 떨어지고, 유지보수도 힘들어진다. 또 하나의 객체에 동일한 이벤트 타입은 중복해서 적용할 수 없다는 단점이 있다.

2) 콜백함수 이용하기

두 번째 방법은 콜백 함수를 이용해 이벤트를 넣는 방법이다.

<body>
  <p id="greeting">안녕하세요</p>
  <script>
    greeting.onmouseover = function(){
      greeting.style.fontSize = "20px";
    } // 적용되지 않음 
    
    greeting.onmouseover = function(){
      greeting.style.color = "red";
    } // 적용
    
    greeting.onmouseout = function(){
      greeting.style.color = "black";
    }
  </script>
</body>

이 또한 하나의 객체에 하나의 이벤트 핸들러만 적용할 수 있다는 단점이 있다. 이벤트 타입이 다르다면 적용이 되지만, 이벤트 타입이 같다면 적용되지 않는다.

여기서, 적용되는 이벤트 핸들러는 맨 마지막에 작성된 이벤트 핸들러이다.

3) addEventListener

마지막은 addEventListener() 메소드를 사용하는 방법이다. 개발자가 가장 추천하는 방법이며, 거의 모든 브라우저에서 지원하는 이벤트 핸들러를 등록하기 위한 메소드이다.

  <p id="greeting">안녕하세요</p>

  <script>
   function fontSize20(){
      greeting.style.fontSize = "20px";
    }

   function fontSize16(){
      greeting.style.fontSize = "16px";
    }
    
   function colorRed(){
      greeting.style.color = "red";
    }
    
    function colorBlack(){
      greeting.style.color = "black";
    }

위의 두 가지 방법과는 다르게 하나의 객체에 여러 이벤트 핸들러를 적용할 수도 있고, 유지보수가 간편하다.


마우스 이벤트

box_over.addEventListener("mouseover", colorPlum); /*마우스 올리면 plum*/
box_over.addEventListener("mouseout", colorPowderblue); /*마우스 빠지면 powder_blue*/

box_enter.addEventListener("mouseenter", colorOrange); /*마우스 올리면 orange*/
box_enter.addEventListener("mouseleave", colorYel); /*마우스 빠지면 yellow*/

box_click.addEventListener("click", colorYelgreen); /*클릭하면 yellowgreen*/
box_click.addEventListener("dblclick", colorPalegreen); /*더블클릭하면 palegreen*/

function colorPlum(){
  box_over.style.backgroundColor = "plum";
  box_over.innerHTML = "mouseover"
}

function colorPowderblue(){
  box_over.style.backgroundColor = "powderblue";
  box_over.innerHTML = "mouseout"
}

function colorOrange(){
  box_enter.style.backgroundColor = "orange";
  box_enter.innerHTML = "mouseenter"
}

function colorYel(){
  box_enter.style.backgroundColor = "yellow";
  box_enter.innerHTML = "mouseleave"
}

function colorYelgreen(){
  box_click.style.backgroundColor = "yellowgreen";
  box_click.innerHTML = "click"
}

function colorPalegreen(){
  box_click.style.backgroundColor = "palegreen";
  box_click.innerHTML = "dblclick"
}

btn.onclick = function(){
  box_over.removeEventListener("mouseover", color_plum);      // 이벤트리스너를 지우는 메소드
  box_over.removeEventListener("mouseout", color_powderblue); // 이벤트리스너를 지우는 메소드
}

over과 enter의 차이점

  • overout자식 요소의 이벤트가 발동하면 부모 요소에 적용한 이벤트까지 함께 발동한다.
    바로 위 부모요소에서 끝나는 것이 아니라, 부모요소에 부모요소가 있다면, 그 부모요소에도 이벤트가 발동하고 이는 최상위 요소까지 이어진다. ( = 이벤트 버블링 )

  • 하지만 enterleave는 자식 요소의 이벤트가 발동해도 부모 요소의 이벤트는 발동되지 않는다.

  • 즉, overout은 자식요소와 부모요소를 독립적으로 본다.

  • enterleave는 자식 요소를 부모요소의 일부분으로 본다.



클릭 이벤트 발동순서

클릭 이벤트에는 mousedown, mouseup, click, dbleclick 이 있다.

  • mousedown: 마우스를 누른 상태
  • mouseup: 마우스를 뗀 상태
  • click: 마우스로 요소를 클릭한 상태
  • dbleclick: 마우스로 요소를 더블클릭한 상태

click 이벤트는 mousedown - mouseup - click 순으로 발동
dblclick 이벤트는 mousedown - mouseup - click - mousedown - mouseup - click - dbleclick 순으로 발동

마우스를 누른 상태에서 이벤트 영역에서 벗어나 마우스를 떼면 mouseup과 click 이벤트가 발동하지 않는다.

<body>
  <div id="box"></div>
<script>
    box.addEventListener("mousedown", colorRed);
box.addEventListener("mouseup", colorYel);
box.addEventListener("click", colorBlue);


function colorRed(){
  box.style.backgroundColor = "red";
}

function colorYel(){
  box.style.backgroundColor = "yellow";
}

function colorBlue(){
  box.style.backgroundColor = "blue";
}
</script>

</body>

박스를 누르면 파란색으로만 바뀌는 것이 아니라, 빨간색 - 노란색 - 파란색 순으로 변경된다.


4. HTML 요소 속성값

1) getAttribute

getAttribute는 문서 객체 내 요소를 선택하고, 그 요소의 속성값을 불러오는 메소드이다.

<body>
  <div id="box">
    <p id="title" name="title">Title</p>
    <img src="img/dog.jpg" alt="#" name="photo"></img>
  </div>
  <script>
    document.getElementsByName("photo").getAttribute("src");  //img/dog.jpg
    document.getElementsByName("photo").src;  //img/dog.jpg
  </script>
</body>

2) setAttribute

setAttribute는 문서 객체 내 요소를 선택하고, 그 요소의 속성 값을 변경하는 메소드이다.

<body>
  <div id="box">
    <p id="title" name="title">Title</p>
    <img src="img/dog.jpg" alt="#" name="photo"></img>
  </div>
  <script>
    document.getElementsByName("photo").setAttribute("src","img/cat.jpg"); // src속성값이 "img/cat.jpg"로 변경
    document.getElementsByName("photo").src = "img/cat.jpg";  // src속성값이 "img/cat.jpg"로 변경
  </script>
</body>



5. 폼 요소

회원가입을 할 때 약관 동의 여부를 묻거나, 가입 양식에 입력한 값이 유효한 값인지 검사하기 위해서는 폼의 속성을 제어할 수 있어야 한다. 그리고 그 폼 속성을 제어하기 위해서는 먼저 폼 요소 선택 방법을 알아야 한다.

입력 요소 선택자

document.폼명.요소명 을 통해 입력 요소를 선택한다.

폼 속성의 종류

  • value : 입력 요소의 value 속성을 변경하거나 값을 가져오는 속성
  • disabled: 입력 요소의 disabled(비활성화) 속성을 변경하거나 현재 상태의 값을 가져오는 속성
  • defaultValue: 입력 요소 초기에 입력된 value 값을 가져오는 속성
  • selected: select 태그의 option의 상태를 가져오는 속성. 선택되어 있을 경우 true, 아니면 false 반환
  • checked: checkbox 또는 radio의 체크 상태를 반환하거나 체크 여부를 제어하는 속성

예제 1. 회원가입 동의

<body>
  <form action="#" method="get" name="form">
    <fieldset>
      <legend>회원가입 동의</legend>
      <div id="terms">
        회사는 법령이 정하는 바에 따라 "회원"의 개인정보를 보호하기 위해 노력합니다. 개인정보의 보호 및 사용에 대해서는 관련법 및 회사의 개인정보취급방침이 적용됩니다.
      </div>
      <div>
        <input type="checkbox" name="accept" id="accept">
        <label for="accept">약관 동의합니다.</label>
      </div>
      <div id="promotion">
        <p>광고성 수신 동의</p>
        <input type="checkbox" name="all_chk" id="all_chk">
        <label for="all_chk">전체선택</label><br>
        <input type="checkbox" name="sub_1" id="sub_1">
        <label for="sub_1">SMS</label><br>
        <input type="checkbox" name="sub_2" id="sub_2">
        <label for="sub_2">Email</label><br>
        <input type="checkbox" name="sub_3" id="sub_3">
        <label for="sub_3">App push</label><br>
      </div>
      <div>
        <input type="submit" value="등록 완료">
        <input type="reset" value="등록 취소">
      </div>
    </fieldset>
  </form>

  <script>
    /*전체 선택 버튼: 체크     >>  전체 선택
      전체 선택 버튼: 체크해제 >>  전체 해제 */
    document.form.all_chk.onclick=function(){
      if(this.checked){
        document.form.sub_1.checked=true;
        document.form.sub_2.checked=true;
        document.form.sub_3.checked=true;
      }else{
        document.form.sub_1.checked=false;
        document.form.sub_2.checked=false;
        document.form.sub_3.checked=false;
      }
    }

    /*약관에 동의하지 않으면 (accept를 체크하지 않으면) 약관 동의 알림 + 약관에 포커스 */
    document.form.onsubmit = function(){
      act = document.form.accept;
      if(act.checked == false){
        alert("약관에 동의해주세요");
        act.focus();
        return false;
      }
    }
  </script>
</body>



예제 2. 견적 계산

<body>
  <h1><span id="name_place">ㅇㅇㅇ</span>님 전기 자동차 견적</h1>
  <form name="form1">
    <input type="checkbox" id="opt1" value="250000" onclick="cost()">
    <label for="opt1">인조가죽세트 / 250000</label><br>
    <input type="checkbox" id="opt2" value="350000" onclick="cost()">
    <label for="opt2">네비게이션 / 350000</label><br>
    <input type="checkbox" id="opt3" value="440000" onclick="cost()">
    <label for="opt3">선루프 / 440000</label><br>

    <h3>차량견적</h3>
    <input name="total" id="total" value="0">
  </form>

  <script>
    function cost() {
      var totalCost = Number(total.defaultValue); //sum 역할 

      for (var i = 1; i <= 3; i++) {
        var option = document.getElementById("opt" + i);
        if (option.checked) {
          totalCost += Number(option.value)
        };
      }
      total.value = totalCost;
    }
    

    var name = "홍길동길동"; //이름

    star = function(name){   // 이름 길이 - 1만큼 * 입력
      stars = "";
      for(i=0; i < name.length - 1; i++){
        stars += "*"
      }
      return stars;
    }

    var f_name = name.substring(0,1);  //성 
    var secret = star(name);           //이름
    name_place.innerHTML = f_name + secret;
  </script>
</body>



예제. 여러 요소에 하나의 이벤트 적용 - forEach문

<body>
  <h1>Title</h1>
  <p id="greeting">안녕하세요</p>
  <p id="hello">Hello</p>
  <h1></h1>

  <script>
    let eventList = document.querySelectorAll('p'); // p만 모두 모아 eventList에 저장
    
    eventList.forEach(function(event){
      event.addEventListener("mouseover", function(){ // 마우스 올리면 적용할 이벤트 
        event.style.fontSize = "20px";
        event.style.color = "red";
      })
      
      event.addEventListener("mouseout", function(){  // 마우스 떼면 적용할 이벤트 
        event.style.fontSize = "16px";
        event.style.color = "black";
      })
    })
  </script>
</body>



예제. 텍스트, 이미지, 버튼을 생성하는 버튼

<body>
  <button onclick = "create_button()">Create Button</button>
  <button onclick = "create_text()">Create Text</button>
  <button id="create_img">Create Image</button>
  <script>

    /*createElement("tag name"): 지정한 tag name의 HTML 요소 생성
      createTextNode("text"): 텍스트 노드 생성

      document.body.appendChild(tag name): 지정한 tag name의 HTML 요소를 body에 추가
      parent tag name.appendChild(tag name): 해당 부모 태그 안에 HTML 요소 추가 */

    function create_button(){
      var br = document.createElement("br");
      var btn = document.createElement("button");
      var text = document.createTextNode("hello World!");
      document.body.appendChild(br);  // body에 br 태그 추가 
      btn.appendChild(text);          // btn (button)안에 텍스트 노드 추가
      document.body.appendChild(btn); // body에 btn(button) 태그 추가 
    }

    function create_text(){
      var h1 = document.createElement("h1");
      var text = document.createTextNode("hello World!");
      h1.appendChild(text);
      document.body.appendChild(h1);
    }
    
    create_img.addEventListener("click", (e) => {
      var img = document.createElement("img");
      var br = document.createElement("br");
      img.setAttribute("src", "img/animal/cat.jpg");
      img.setAttribute("width", "500px");
      document.body.appendChild(br);
      document.body.appendChild(img);
    })
  </script>
</body>
profile
프론트엔드 개발 및 실무 프로젝트 구현과정 수료

0개의 댓글