DOM(Document Object Model) 은 HTML, XML 구조화된 문서를 객체 지향적으로 표현한 프로그래밍 interface 이다. DOM은 동적으로 문서의 내용, 구조, 스타일에 접근하고 변경하는 수단으로 W3C 에서 표준화한 여러 개의 API의 기반이 된다. DOM 은 구조화된 nodes와 property 와 method 를 갖고 있는 objects로 문서를 표현한다. 이들은 웹 페이지를 스크립트 또는 프로그래밍 언어들에서 사용될 수 있게 연결시켜주는 역할을 담당한다.

DOM Programming Interface

모든 HTML elements는 객체로 정의하며 인터페이스는 객체에 대한 프로퍼티와 메서드로 구성된다. Property 는 element value 이고 Method 는 element 조작을 하는 행위이다.

두 가지 예를 보면 아래와 같다.

  • getElementById() 메서드는 ID를 이용해 element 탐색을 한다.
  • innerHTML 프로퍼티는 element 의 content 조작을 한다.

최근의 유행하는 React, Angular, Vue 는 DOM API 기반으로 문서 조작을 위한 편리한 기능을 제공하는 프레임워크이다.

선택자

querySelector() 메서드 이용시 파라미터로 CSS 선택자를 넣어줘야 한다. 선택자의 구분은 아래와 같이 구분한다. querySelector()는 HTMLCollection 아닌 첫 번째 element 를 반환한다.

  • querySelector("li") : li 태그 탐색
  • querySelector(".className") : className 클래스 탐색
  • querySelector("#idName") : idName id 탐색

polyfill

사용자가 이용하는 브라우저 버전은 모두 다르며, 각 브라우저 마다 다른 기능을 가지고 있어 파편화가 발생한다. polyfill은 구형 브라우저에서 지원하지 않는 기능(ex, HTML5 API)을 지원하여 최신 브라우저와 같은 동작을 하게끔 하위 호환성을 맞춰준다.

실습

<body>
  <h1>selector test</h1>
  <section>
    <h2> red section </h2>
    <ul>
      <li class="red">apple</li>
      <li class="red">orange</li>
      <li>banana</li>
      <li>grape</li>
      <li>strawberry</li>
    </ul>
  </section>
  <Br>
  <section>
    <h2> blue section </h2>
    <ul>
      <li class="green blue">apple</li>
      <li class="red">orange</li>
      <li>banana</li>
      <li>grape</li>
      <li>strawberry</li>
    </ul>
  </section>
</body>
  1. 새로운 과일 추가

    var sb = document.querySelector("ul");
    var potato = document.createElement("li");
    potato.innerText = 'potato';
    sb.appendChild(potato);
  2. insertBefore메서드를 사용해서, orange와 banana 사이에 새로운 과일을 추가

    var banana = document.querySelector('li:nth-child(3)');
    var potato = document.createElement('li');
    potato.innerText = 'potato';
    document.querySelector('ul').insertBefore(potato, banana);
  3. insertAdjacentHTML메서드를 사용해서, orange와 banana 사이에 새로운 과일을 추가

    var banana = document.querySelector('li:nth-child(3)');
    banana.insertAdjacentHTML('beforebegin', '<li> potato </li>');
  4. apple을 grape 와 strawberry 사이로 옮기시오.

    var apple = document.querySelector('li');
    var banana = document.querySelector('li:nth-child(4)');
    banana.insertAdjacentElement('afterend', apple);
  5. class 가 'red'인 노드만 삭제하시오.

    var ul = document.querySelector('ul');
    var reds = document.querySelectorAll('li.red');
    for (i = 0, len = reds.length; i < len; ++i) {
      ul.removeChild(reds[i]);
    }
  6. section 태그의 자손 중에 blue라는 클래스를 가지고 있는 노드가 있다면, 그 하위에 있는 h2 노드를 삭제

// 재귀 이용...
function rec(element) {
  let children = element.children;
  if(children.length < 1) {  return element.classList.contains('blue');  }

  for(let item of children) {
    if(item.className == 'blue') {  return true;  }
    if(children.length >= 1 && rec(item)) {  return true;  }

  }

  return false;

}

var section = document.getElementsByTagName('section');

for(let sec of section) {
  if(rec(sec)) {
    sec.removeChild(sec.querySelector('h2'));

  }

}

// CSS 선택자 이용 ==> 권장 방법
let blueNode = document.querySelectorAll('section .blue');

for(let item of blueNode) {
  let section = item.closest('section');
  let h2 = section.querySelector('h2');
  section.removeChild(h2);

}

참고