210806 CodeStates 15일차

공윤배·2021년 8월 9일
0

210806 CodeStates 15일차(DOM)

블로그의 내용은 코드스테이츠의 자료와 PoiemaWeb을 참고해 공부한 내용입니다.

DOM(Document Object Model)

HTML로 작성된 웹문서를 웹브라우저에 렌더링하려면 웹문서를 브라우저가 이해할 수 있는 구조로 변환하여 메모리에 저장해야한다.
브라우저의 렌더링엔진은 웹문서를 파싱하여 브라우저가 이해할 수 있는 구조로 변환한다.
웹문서의 모든요소와 요소들의 모든 어트리뷰트, 텍스트를 각각의 객체로 변환하고 변환한 객체들을 부자관계로 표현할수 있는 트리구조로 구성한 것이 DOM tree이다.

DOM은 자바스크립트를 통해 동적으로 변경될 수 있으며, 변경된 DOM은 웹브라우저에 표현되는 렌더링에만 반영된다.(원본 HTML문서가 변하지는 않는다.)
정적인 웹페이지에 접근하여 동적으로 웹페이지를 변경하기 위해서는 메모리에 저장된 DOM을 변경해야하고, 이때 DOM에 접근하고 변경하기 위한 프로퍼티와 메서드들을 DOM API라고 부른다.

DOM의 두가지 기능

  • HTML문서에 대한 모델구성
    브라우저가 HTML문서를 파싱하며 해당문서들의 모든 요소를 객체(노드)로 변환하고 트리구조로 DOM tree로 만들어 메모리에 저장한다.
  • HTML문서내의 요소에 접근/수정
    DOM은 모델(DOM tree)의 객체들에 접근하고 수정할 수 있는 프로퍼티와 메서드(DOM API)를 제공한다.

DOM tree의 최상위 객체는 document객체이며 해당 웹페이지의 모든 요소를 포함하고 있다.
DOM tree는 네종류의 노드로 구성된다.

  • 문서노드(Document Node)
    트리의 최상위에 존재하며 모든 요소,어트리뷰트,텍스트 노드에 접근하려면 문서노드를 통해 접근할 수 있다.
    DOM tree에 접근하기 위한 시작점이다.
  • 요소노드(Element Node)
    요소노드는 HTML요소를 표현한다.
    HTML요소는 중첩에 의해 부자관계를 가지며 요소노드도 부자관계를 통해 정보를 구조화한다.
  • 어트리뷰트노드(Attribute Node)
    어트리뷰트노드는 HTML요소의 어트리뷰트를 표현한다.
    요소노드의 자식노드가 아닌 해당요소의 일부로 표현된다.
  • 텍스트노드(Text Node)
    HTML요소의 텍스트를 표현한다.
    텍스트 노드는 자식노드를 가질수 없으며 DOM tree의 최종단이다.

DOM API

DOM을 통해 웹페이지를 조작(manipulate)하기 위해서는 DOM이 제공하는 DOM API의 다양한 프로퍼티와 메서드들을 이용한다.
DOM API는 다음과 같은 프로퍼티와 메서드를 제공한다.

예제 HTML문서

  <div id="olContainer">
    Oldered List
    <ol id="orderedList" class="list">
      <li>first element</li>
      <li>second element</li>
      <li>third element</li>
      <li>forth element</li>
    </ol>
  </div>
  <div id="ulContainer">
    Unordered list
    <ul id="unorderdList" class="list">
      <li>first element</li>
      <li>second element</li>
      <li>third element</li>
      <li>forth element</li>
    </ul>
  </div>

document.getElementById(id)
매개변수로 주어진 값을 id로 갖는 요소노드를 선택한다.

document.getElementById('orderedList');
// id값이 orderedList인 요소(ol)노드를 선택한다.

document.querySelector(cssSelector)
매개변수로 주어진 css의 선택자에 해당하는 요소노드를 선택한다.
복수개의 요소일 경우 첫번째 요소노드만 선택한다.

document.querySelector('.list');
//class값이 list인 요소는 ol,ul요소 두개지만 첫번째 요소 ol노드를 선택한다.

document.querySelectorAll(cssSelector)
매개변수로 주어진 css선택자에 해당하는 모든 요소들을 선택한다.
선택된 요소들을 NodeList에 담아 반환한다.

document.querySelector('.list');
//NodeList(2) [ol#orderedList.list, ul#unorderdList.list]
//ol,ul 두개의 요소 모두 NodeList에 담아 반환된다.

Node.parentNode
해당노드의 부모노드를 탐색한다.

let ol=document.querySelector('#orderedList');
ol.parentNode;
// div#olConatainer  ol요소를 포함하는 div요소노드

Node.firstChild, Node.lastChild
해당노드의 자식노드를 탐색한다.(첫번째 자식노드, 마지막 자식노드)

Node.firstElementChild, Node.lastElementChild
해당노드의 자식노드중 요소노드를 탐색한다.(첫번째 요소노드, 마지막 요소노드)

ol.firstChild
//  #text
ol.firstElementChild
//  <li>first element</li>

ol의 첫번째 요소노드(firstElementChild)는 예상한대로 li 요소가 나왔지만 첫번째 자식노드는 text라는 결과가 나왔다.
대부분의 웹브라우저는 HTML문서상의 공백문자,줄바꿈문자를 텍스트노드로 취급하기 때문이다.

위의 HTML을 다시한번 살펴보면

    <ol id="orderedList" class="list">
      <li>first element</li>
      <li>second element</li>
      <li>third element</li>
      <li>forth element</li>
    </ol>

첫번째 줄(ol요소가 있는줄)에서 줄바꿈이 일어나고 다음줄의 들여쓰기로 인한 공백까지 텍스트 노드로 취급하기 때문에 ol의 자식노드중 첫번째 노드는 '\n    '의 값을 갖는 텍스트 노드가 된다.

Node.hasChildNodes()
해당노드가 자식노드가 있는지 확인하고 Boolean값을 반환한다.

ol.hasChildNodes()
// true

Node.childNodes
해당노드의 모든 자식노드들을 NodeList에 담아 반환한다.

ol.childNodes
// NodeList(9) [text, li, text, li, text, li, text, li, text]
// 중간의 text노드들은 HTML문서상의 줄바꿈과 들여쓰기의 값을 갖는 텍스트 노드이다.

Node.children
해당노드의 자식노드중 모든 요소노드를 HTMLCollection에 담아 반환한다.

ol.children
// HTMLCollection(4) [li, li, li, li]

Node.className,Node.classList
요소노드의 class어트리뷰트에 접근한다.
className은 문자열의 형태로, classList는 DOMTokenList의 형태로 반환한다.
classList는 add(값 추가),remove(값 제거),contains(포함하는지 여부)의 메서드를 제공한다.
요소노드의 class값을 수정할 수 있다.

ol.classList
// DOMTokenList ["list", value: "list"]
ol.classList.add('ordered')
ol.classList
// DOMTokenList(2) ["list", "ordered", value: "list ordered"]
ol.className
// "list ordered"

Node.textContent
해당노드의 텍스트 컨텐츠를 취득한다.
textContent를 통해 새로운 문자열을 할당하여 텍스트 컨텐츠를 변경할 수 있다.
마크업을 무시하며 문자열로만 인식한다.

Node.innerHTML
해당요소의 모든 자식노드를 포함하는 컨텐츠를 하나의 문자열로 취득한다.
마크업을 인식한다. 따라서 크로스 스크립팅 공격에 취약하다.

let olDiv=document.querySelector('#olConatainer');
olDiv.textContent;
//"\n    Oldered List\n    \n      first element\n      second element\n      third element\n      forth element\n    \n  "

olDiv.innerHTML;
//"\n    Oldered List\n    <ol id=\"orderedList\" class=\"list\">\n      <li>first element</li>\n      <li>second element</li>\n      <li>third element</li>\n      <li>forth element</li>\n    </ol>\n  "

마크업을 인식하는 innerHTML은 재할당시에도 마크업을 인식하기 때문에 태그를 이용한 요소를 문자열로 할당하면 태그로 인식된다.

document.createElement(tagName)
매개변수로 전달받은 값을 태그로 하는 HTML요소를 생성한다.

parentNode.appendChild(Node)
매개변수로 전달받은 노드를 부모노드의 노드리스트 마지막에 붙인다.

parentNode.removeChild(Node)
매개변수로 전달받은 노드를 DOM tree에서 제거한다.

let li=document.createElement('li');
// 새로운 li요소를 생성한다.
li.textContent='fifth element';
//li의 텍스트 컨텐츠를 변겅
ol.appendChild(li);
//ol의 마지막 부분에 li요소를 추가
//웹페이지가 변경된다.

ol.removeChild(li);
//ol의 자식노드중 li를 DOM tree에서 제거한다.
//웹페이지가 변경된다.

0개의 댓글