모던 자바스크립트 딥다이브Chapter39

HYEON17·2023년 2월 15일
0

WIL

목록 보기
10/13
post-thumbnail

39장: DOM

HTML 문서의 계층적 구조와 정보를 표현하며 이를 제어할 수 있는 API, 프로퍼티와 메서드를 제공하는 트리 자료구조

39.1 노드

39.1.1 HTML 요소와 노드 객체

노드 객체들로 구성된 트리 자료구조를 DOM 이라 한다

39.1.2 노드 객체의 타입

문서 노드

  • 문서노드, 즉 document 객체는 DOM트리의 루트 노드 이므로 DOM 트리의 노드들에 접근하기 위한 진입점 역할을 담당
  • 요소, 어트리뷰트, 텍스트 노드에 접근하려면 문서 노드를 통해야 한다

요소 노드

  • HTML요소를 가리키는 객체
  • HTML요소간의 중첩에 의해 부자 관계를 가지며, 이 관계를 통해 정보를 구조화

어트리뷰트 노드

  • 부모 노드와 연결되어 있지 않고 요소 노드에만 연결
  • 참조 또는 변경시 먼저 요소 노드에 접근해야 한다

텍스트 노드

  • 문서의 정보를 표현
  • 요소 노드의 자식 노드이며, 자식 노드를 가질 수 없는 리프 노드이다
  • DOM트리의 최종단

39.1.3 노드 객체의 상속 구조


DOM은 HTML 문서의 계층적 구조와 정보를 표현하는 것은 물론 노드 객체의 종류, 즉 노드 타입에 따라 필요한 기능을 프로퍼티와 메서드의 집합인 DOM API로 제공

39.2 요소 노드 취득

39.2.1 id를 이용한 요소 노드 취득

중복된 id값을 갖는 요소가 여러개 존재할 경우 인수로 전달된 id값을 갖는 첫 번째 요소 노드만 반환

39.2.2 태그 이름을 이용한 요소 노드 취득

  • getElementsByTagName 메서드는 여러 개의 요소 노드 객체를 갖는 DOM 컬렉션 객체인 HTMLCollection 객체를 반환
    • HTMLCollection 객체는 유사 배열 이면서 이터러블

39.2.3 class를 이용한 요소 노드 취득

  • getElementsByClassName메서드는 인수로 전달한 class어트리뷰트 값을 갖는 모든 요소 노드들을 탐색하여 반환
  • 인수로 전달할 class값은 공백으로 구분하여 여러 개의 class를 지정할 수 있다
  • HTMLCollection 객체를 반환

39.2.5 특정 요소 노드를 취득할 수 있는지 확인

Element.prototype.matches 메서드는 인수로 전달한 css 선택자를 통해 특정 요소 노드를 취득할 수 있는지 확인

39.2.6 HTMLCollection과 NodeList

  • DOM API가 여러 개의 결과값을 반환하기 위한 DOM컬렉션 객체
  • 유사배열객체이면서 이터러블

39.3 노드 탐색

39.3.2 자식 노드 탐색


39.3.3 자식 노드 존재 확인

  • Node.prototype.hasChildNodes 메서드 사용
  • 자식 노드가 존재하면 true, 존재하지 않으면 false 반환
  • 텍스트 노드를 포함하여 자식 노드의 존재를 확인

39.4 노드 정보 취득

39.5 요소 노드의 텍스트 조작

39.5.1 nodeValue

getter, setter 모두 존재하므로 참조와 할당 모두 가능

39.5.2 textContent

getter, setter 모두 존재하는 접근자 프로퍼티로서 요소 노드의 텍스트와 모든 자손 노드의 텍스트를 모두 취득하거나 변경한다

39.6 DOM 조작

DOM에 새로운 노드가 추가되거나 삭제되면 리플로우와 리페인트가 발생하여 성능에 영향을 주므로 주의해서 다루어야 한다

39.6.1 innerHTML

getter, setter 모두 존재하는 접근자 프로퍼티로서 요소 노드의 HTML 마크업을 취득하거나 변경한다

39.6.2 insertAdjacentHTML 메서드

기존 요소를 제거하지 않으면서 위치를 지정해 새로운 요소를 삽입

39.6.3 노드 생성과 추가

<!DOCTYPE html>
<html>
  <body>
    <ul id="fruits">
      <li>Apple</li>
    </ul>
  </body>
  <script>
    const $fruits = document.getElementById('fruits');

    // 1. 요소 노드 생성
    const $li = document.createElement('li');

    // 2. 텍스트 노드 생성
    const textNode = document.createTextNode('Banana');

    // 3. 텍스트 노드를 $li 요소 노드의 자식 노드로 추가
    $li.appendChild(textNode);

    // 4. $li 요소 노드를 #fruits 요소 노드의 마지막 자식 노드로 추가
    $fruits.appendChild($li);
  </script>
</html>

39.6.4 복수의 노드 생성과 추가

DocumentFragment를 사용하면 DOM변경이 한번 발생되므로 리플로우와 리페인트가 한번만 발생되어 성능에 유리

<!DOCTYPE html>
<html>
  <body>
    <ul id="fruits"></ul>
  </body>
  <script>
    const $fruits = document.getElementById('fruits');

    // DocumentFragment 노드 생성
    const $fragment = document.createDocumentFragment();

    ['Apple', 'Banana', 'Orange'].forEach(text => {
      // 1. 요소 노드 생성
      const $li = document.createElement('li');

      // 2. 텍스트 노드 생성
      const textNode = document.createTextNode(text);

      // 3. 텍스트 노드를 $li 요소 노드의 자식 노드로 추가
      $li.appendChild(textNode);

      // 4. $li 요소 노드를 DocumentFragment 노드의 마지막 자식 노드로 추가
      $fragment.appendChild($li);
    });

    // 5. DocumentFragment 노드를 #fruits 요소 노드의 마지막 자식 노드로 추가
    $fruits.appendChild($fragment);
  </script>
</html>

39.6.5 노드 삽입

마지막 노드로 추가

Node.prototype.appendChild

<!DOCTYPE html>
<html>
  <body>
    <ul id="fruits">
      <li>Apple</li>
      <li>Banana</li>
    </ul>
  </body>
  <script>
    // 요소 노드 생성
    const $li = document.createElement('li');

    // 텍스트 노드를 $li 요소 노드의 마지막 자식 노드로 추가
    $li.appendChild(document.createTextNode('Orange'));

    // $li 요소 노드를 #fruits 요소 노드의 마지막 자식 노드로 추가
    document.getElementById('fruits').appendChild($li);
  </script>
</html>

지정한 위치에 노드 삽입

Node.prototype.insertBefore(newNode, childNode)

<!DOCTYPE html>
<html>
  <body>
    <div>test</div>
    <ul id="fruits">
      <li>Apple</li>
      <li>Banana</li>
    </ul>
  </body>
  <script>
    const $fruits = document.getElementById('fruits');

    // 요소 노드 생성
    const $li = document.createElement('li');

    // 텍스트 노드를 $li 요소 노드의 마지막 자식 노드로 추가
    $li.appendChild(document.createTextNode('Orange'));

    // 두 번째 인수로 전달받은 노드는 반드시 #fruits 요소 노드의 자식 노드이어야 한다.
    $fruits.insertBefore($li, document.querySelector('div'));
    // DOMException
  </script>
</html>

 // 두 번째 인수로 전달받은 노드가 null이면 $li 요소 노드를 #fruits 요소 노드의 마지막 자식 노드로 추가
    $fruits.insertBefore($li, null);

39.6.6 노드 이동

appendChild,insertBefore 메서드를 사용하여 DOM에 다시 추가하면 현재 위치에서 노드를 제거하고 새로운 위치에 노드를 추가 즉, 노드가 이동

39.6.7 노드 복사

Node.prototype.cloneNode([deep: true | false]) 메서드는 노드의 사본을 생성하여 반환

39.6.8 노드 교체

Node.prototype.replaceChild(newChild,oldChild)메서드는 자신을 호출한 노드의 자식 노드를 다른 노드로 교체

39.6.9 노드 삭제

Node.prototype.removeChild(child) 메서드는 child매개변수에 인수로 전달한 노드를 DOM에서 삭제

39.7 어트리뷰트

39.7.1 어트리뷰트 노드와 attributes 프로퍼티

모든 어트리뷰트 노드의 참조는 유사 배열 객체이자 이터러블인 NamedNodeMap객체에 담겨서 요소 노드의 attributes 프로퍼티에 저장

attributes 프로퍼티는 getter만 존재하는 읽기 전용 접근자 프로퍼티

39.7.2 HTML 어트리뷰트 조작

Element.prototype.getAttribute/setAttribute 메서드를 사용하면 attribute 프로퍼티를 통하지 않고 요소 노드에서 메서드를 통해 직접 HTML 어트리뷰트 값을 취득하거나 변경할 수 있다
특정 어트리뷰트 존재 확인은 Element.prototype.hasAttribute를 사용
삭제시 Element.prototype.removeAtrribute를 사용

39.7.3 HTML 어트리뷰트 vs. DOM 프로퍼티

HTML 어트리뷰트 값은 HTML 요소의 초기 상태를 의미

39.7.4 data 어트리뷰트와 dataset 프로퍼티

data 어트리뷰트와 dataset 프로퍼티 사용시 HTML요소에 정의한 사용자 정의 어트리뷰트와 자바스크립트 간에 데이터를 교환가능

<!DOCTYPE html>
<html>
<body>
  <ul class="users">
    <li id="1" data-user-id="7621" data-role="admin">Lee</li>
    <li id="2" data-user-id="9524" data-role="subscriber">Kim</li>
  </ul>
  <script>
    const users = [...document.querySelector('.users').children];

    // user-id가 '7621'인 요소 노드를 취득한다.
    const user = users.find(user => user.dataset.userId === '7621');
    // user-id가 '7621'인 요소 노드에서 data-role의 값을 취득한다.
    console.log(user.dataset.role); // "admin"

    // user-id가 '7621'인 요소 노드의 data-role 값을 변경한다.
    user.dataset.role = 'subscriber';
    // dataset 프로퍼티는 DOMStringMap 객체를 반환한다.
    console.log(user.dataset); // DOMStringMap {userId: "7621", role: "subscriber"}
  </script>
</body>
</html>

39.8 스타일

39.8.1 인라인 스타일 조작

HTMLElement.prototype.style 프로퍼티는 setter와 getter모두 존재하는 접근자 프로퍼티로서 요소 노드의 인라인 스타일을 취득하거나 추가 또는 변경 한다

39.8.2 클래스 조작

className

어트리뷰트 값을 문자열로 반환 값을 할당한 문자열로 변경

classList

class 어트리뷰트의 정보를 담은 DOMTokenList객체를 반환
DOMTokenList객체는 컬렉션 객체로서 유사 배열 객체이면서 이터러블

39.8.3 요소에 적용되어 있는 CSS 스타일 참조

getComputedStyle메서드를 사용
의사 요소를 지정하는 문자열을 전달 가능

profile
프론트엔드 개발자

0개의 댓글