Skip to content

Latest commit

 

History

History
166 lines (143 loc) · 5.81 KB

DOM API.md

File metadata and controls

166 lines (143 loc) · 5.81 KB

DOM API

브라우저에서는 W3C DOM, WHATWG DOM 표준에 근거하여 노드의 형태로 DOM을 구현하고, 이를 사용하기 위한 프로퍼티와 메소드를 제공한다. 이 프로퍼티와 메소드의 집합을 DOM API라고 한다. 구현된 DOM은 OOP의 형태라 대체로 객체로 제공되기 때문에 javascript와 같은 스크립트 기반 언어가 접근하여 수정할 수 있다.


요소 접근

getElementById

<p id="getId">getId</p>

<script>
    document.getElementById("getId");
</script>

id 속성값으로 Element node를 하나 선택한다.

(출력값) <p id="getId">getId</p>

getElementsByClassName

<p class="getClass">class1</p>
<p class="getClass">class2</p>
<p class="getClass">class3</p>
<p class="getClass">class4</p>

<script>
    document.getElementsByClassName("getClass");
</script>

(출력값) HTMLCollection(4) [p.getClass, p.getClass, p.getClass, p.getClass]

class 속성값으로 모든 Element node를 선택한다.
선택된 node들은 HTMLCollection으로 반환된다. HTMLCollection유사배열이며, 실시간으로 node의 변경이 반영된다. 따라서 다음과 같은 특징을 갖는다.

  • 배열 메소드를 사용할 수 없다.

    var classes = document.getElementsByClassName("getClass");
    classes.forEach(el => el.innerText = "changed");
    //에러발생
  • length 속성과 index를 사용할 수 있다.

  • 클래스 변동시 반복문 사용에 유의해야한다.

    var classes = document.getElementsByClassName("getClass");
    for(let i = 0; i<classes.length; ++i){
        classes[i].className = "changed";
    }

    예상대로라면 classes[0]부터 classes[3]까지 요소들의 className이 바뀌었을 것 같지만 실제로는 classes[0]classes[2]의 className만 바뀐다. 이유는 다음과 같다.

    1. i=0일 때 classes.length = 4이고 classes[0]HTMLCollection의 첫번째 요소를 가리킨다. className이 변경된 후 HTMLCollection에 node의 변경이 실시간으로 적용된다. 즉, HTMLCollection의 첫번째 요소가 사라져 lengthindex가 다음과 같이 변경된다.
      HTMLCollection
    2. 따라서 i=1일 때 classes.length = 3이 되고 classes[1]는 이전 HTMLCollection의 세번째 요소를 가리키게 된다.
    3. 또 다시 node의 변경이 적용되어 classes.length = 2가 되어 반복문이 종료된다.

    이 문제를 해결하기 위해 다음 방법들을 쓸 수 있다.

    • 반복문을 역방향으로 돌린다.
      var classes = document.getElementsByClassName("getClass");
      for(let i=classes.length-1; i >= 0; --i){
          classes[i].className = "changed";
      }
    • HTMLCollection을 배열로 변경한다.
      • Spread 이용
      var classes = document.getElementsByClassName("getClass");
      var arrClass = [...classes]; 
      for(let i=0; i < arrClass.length; ++i){
          arrClass[i].className = "changed";
      }
      • Array.from 이용
      var classes = document.getElementsByClassName("getClass");
      var arrClass = Array.from(classes);
      for(let i=0; i < arrClass.length; ++i){
         arrClass[i].className = "changed";
      }

querySelector & querySelectorAll

querySelectorquerySelectorAll를 이용하면 #, ., input[type=text] 등과 같은 css 선택자로 요소에 접근할 수 있다.
querySelectorAll은 가져온 모든 요소를 NodeList로 가져온다. NodeListHTMLCollection과 달리 node의 변동이 실시간으로 적용되지 않는다.


요소 탐색

  • 노드탐색
    parentNode
    childNode, firstChild, lastChild
    previousSibling, nextSibling 등
  • 요소탐색
    children, firstElementChild, lastElementChild
    previousElementSibling, nextElementSibling 등

노드 탐색 시 주의해야할 점은 요소간의 공백도 텍스트 노드로 취급한다는 것이다. 따라서 탐색결과가 기대와 다를 수 있다.

<ul>
    <li id="a" class="1"></li>  
    <li id="b" class="2"></li>
    <li class="3"></li>
</ul>

즉, li.anextSibling으로 li.b를 기대했지만 공백이 반환될 수도 있다. 이런 상황을 피하기 위해 위의 요소 탐색을 할 수 있다.
또한 여러 요소가 반환되는 경우 노드 탐색은 NodeList로, 요소 탐색 HTMLCollection으로 반환된다.


요소 조작 - classList

classList에는 다음과 같은 메소드가 있다.

var target = document.getElementById("target");
target.classList.add('added');
target.classList.remove('added');
target.classList.contains('added'); //boolean 반환
target.classList.replace('target', 'changed');
target.classList.toggle('active');

특히 다음과 같이 toggle을 사용하는 경우, addremove를 일일이 해줄 필요가 없기 때문에 매우 편리하다.

<body>
    <div class="bg">
        <button id="btn"></button>
    </div>
</body>
.bg {
    background: #e2e2e2;
    border-radius: 15px;
    width: 70px;
}

#btn {
    position: relative;
    height: 30px;
    width: 30px;
    outline: none;
    background: white;
    border-radius: 15px;
}

.toggleTrue {
    left: 40px;
}
document.getElementById("btn").addEventListener("click", function(e){
    let target = e.target;
    target.classList.toggle('toggleTrue');
});


Reference

문서 객체 모델(Document Object Model)