Chapter 39 DOM

samuel Jo·2023년 6월 23일
0

딥다이브

목록 보기
33/34

HTML 문서를 파싱하여 브라우저가 이해할 수 있는 자료구조인 DOM을 생성.

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

39.1 노드

39.1.1 HTML요소와 노드 객체

HTML요소의 어트리뷰트는 노드로
HTML요소의 텍스트 콘텐츠는 텍스트 노드로 변환.

요소 노드 = div - class="greeting" 어트리뷰트 노드
텍스트 노드 = "Hello"

HTML요소간에는 중첩관계에 의해 계층적인 부자 관계가 형성. 이러한 HTML요소간의 부자관계를 반영하여 HTML문서의 구성요소인 HTML욧를 객체화한 모든 노드 객체들을 트리자료 구조로 구성.

트리자료구조
트리자료구조는 노드들의 계층 구조로 이뤄짐. 트리자료구조는 부모노드와 자식노드로 구성돠어 노드간의 계층적 구조를 표현하는 비선형 자료구조를 말함.

비선형 자료구조 = 하나의 자료뒤에 여러개의 자료가 존재할 수 있는 자료구조. ex)트리,그래프
선형 자료 구조 = 하나의 자료뒤에 하나의 자료만 존재하는 자료 구조 . ex)배열,스택,큐,리스트,해시테이블

노드 객체들로 구성된 트리 자료구조를 DOM으로 부름. 노드객체의 트리로 구조화 되어있어 DOM트리라고도 함.

39.1.2 노드 개체의 타입

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <link rel="stylesheet" href="style.css">
  </head>
  <body>
    <ul>
      <li id="apple">Apple</li>
      <li id="banana">Banana</li>
      <li id="orange">Orange</li>
    </ul>
    <script src="app.js"></script>
  </body>
</html>

공백 텍스트 노드
HTML요소 사이의 개행이나 공백은 텍스트 노드가 됨.

문서노드

document 객체를 가리킴. document객체는 브라우저가 렌더링한 HTML문서 전체를 가리키는 객체로서 전역 객체인 window 의 document 프로퍼티에 바인딩 되어있음.
window.document or document로 참조 할 수 있음.
DOM트리의 루트 노드이므로 DOM트리의 노드들에 접근하기 위한 "진입점" 역할을 담당.

요소 노드

HTML요소를 가리키는객체 요소노드는 HTML 요소간의 중첩에 의해 부자관계를 가지며 이 관계를 통해 정보를 구조화함. 문서의 구조를 표현한다 라고 할 수 있음.

어트리뷰트 노드
HTML요소의 어트리뷰트를 가리키는 객체.
요소노드 - 부모노드와 연결
어트리뷰트 노드 - 부모노드연결X 요소노드에만 연결.

텍스트 노드
html요소의 텍스트를 가리키는 객체.
요소노드- 문서의 구조
텍스트노드- 정보 표현
자식 노드를 가질 수 없는 리프 노드. DOM트리의 최종단 텍스트 노드에 접근하려면 먼저 부모노드인 요소노드에 접근해야함.
innerHTML


39.1.3 노드 객체의 상속 구조

39.2 요소 노드 취득

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

Document.prototype.getElementById 메서드로 취득
인수로 전달한 id 어트리뷰트 값과 일치하는 요소 노드를 반환
만약 해당 id를 갖는 요소가 여러개면 맨 처음 노드를 반환
일치하는 요소 노드가 없으면 null 반환

HTML 요소에 id 어트리뷰트를 부여하면 id값과 동일한 이름의 전역 변수가 암묵적으로 생성되고 해당 노드 객체가 할당되는 부수 효과 발생
만약 id값과 동일한 전역 변수가 이미 있으면 이 변수에 노드 객체가 할당되지는 않음

<!DOCTYPE html>
<html>
  <body>
    <ul>
      <li id="apple">Apple</li>
      <li id="banana">Banana</li>
      <li id="orange">Orange</li> <!--글씨 색깔 오렌지 -->
      <li id="orange">Orange2</li>
    </ul>
    <script>
      const $elem = document.getElementById('orange');
      $elem.style.color = 'orange';
      let apple = '사과';
      console.log(orange); // orange 노드 객체 
      console.log(apple); // '사과'
      console.log(banana); // banana 노드 객체
      
    </script>
  </body>
</html>

id값은 HTML 문서 내에서 유일한 값이어야 하며, class 어트리뷰트와 달리 공백문자로 구분하여 여러개의 값을 가질수 없음. 단 중복된 id값을 갖는 HTML요소가 여러개 존재하더라도 어떠한 에러도 발생하지 않음. HTML문서 내에서는 중복된id값을 갖는 요소가 여러개 존재할 가능성이 있음.

이러한 경우 getElementById메서드는 인수로 전달된id값을 갖는 첫 번째 요소 노드만 반환 .
즉 getElementById 메서드는 언제나 단하나의 요소 노드를 반환.

<!DOCTYPE html>
<html>
  <body>
    <ul>
      <li id="banana">Apple</li>
      <li id="banana">Banana</li>
      <li id="banana">Orange</li>
    </ul>
    <script>
      // getElementById 메서드는 언제나 단 하나의 요소 노드를 반환한다.
      // 첫 번째 li 요소가 파싱되어 생성된 요소 노드가 반환된다.
      const $elem = document.getElementById('banana');

      // 취득한 요소 노드의 style.color 프로퍼티 값을 변경한다.
      $elem.style.color = 'red';
    </script>
  </body>
</html>

인수로 전달된 id값을 갖는 HTML 요소가 존재하지 않는 경우 getElementById 메서드는 null을 반환.

<!DOCTYPE html>
<html>
  <body>
    <ul>
      <li id="apple">Apple</li>
      <li id="banana">Banana</li>
      <li id="orange">Orange</li>
    </ul>
    <script>
      // id 값이 'grape'인 요소 노드를 탐색하여 반환한다. null이 반환된다.
      const $elem = document.getElementById('grape');

      // 취득한 요소 노드의 style.color 프로퍼티 값을 변경한다.
      $elem.style.color = 'red';
      // -> TypeError: Cannot read property 'style' of null
    </script>
  </body>
</html>

HTML 요소에 id 어트리뷰트를 부여하면 id값과 동일한 이름의 전역 변수가 암묵적으로 선언되고 해당 노드 객체ㅏ 할당되는 sideEffect.

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

Document.prototype.getElementsByTagName 메서드로 취득
인수로 전달한 태그인 모든 요소 노드를 갖는 HTMLCollection 객체를 반환

<!DOCTYPE html>
<html>
  <body>
    <ul>
      <li id="apple">Apple</li>
      <li id="banana">Banana</li>
      <li id="orange">Orange</li>
    </ul>
    <script>
      // 태그 이름이 li인 요소 노드를 모두 탐색하여 반환한다.
      // 탐색된 요소 노드들은 HTMLCollection 객체에 담겨 반환된다.
      // HTMLCollection 객체는 유사 배열 객체이면서 이터러블이다.
      const $elems = document.getElementsByTagName('li');

      // 취득한 모든 요소 노드의 style.color 프로퍼티 값을 변경한다.
      // HTMLCollection 객체를 배열로 변환하여 순회하며 color 프로퍼티 값을 변경한다.
      [...$elems].forEach(elem => { elem.style.color = 'red'; });
    </script>
  </body>
</html>

해당 요소 노드가 없으면 빈 HTMLCollection 객체 반환
HTMLCollection 객체는 유사 배열 객체,이터러블임

모든 노드 선택시 '*'

// 모든 요소 노드를 탐색하여 반환한다.
const $all = document.getElementsByTagName('*');
// -> HTMLCollection(8) [html, head, body, ul, li#apple, li#banana, li#orange, script, apple: li#apple, banana: li#banana, orange: li#orange]
<!DOCTYPE html>
<html>
  <body>
    <ul id="fruits">
      <li>Apple</li>
      <li>Banana</li>
      <li>Orange</li>
    </ul>
    <ul>
      <li>HTML</li>
    </ul>
    <script>
      // DOM 전체에서 태그 이름이 li인 요소 노드를 모두 탐색하여 반환한다.
      const $lisFromDocument = document.getElementsByTagName('li');
      console.log($lisFromDocument); // HTMLCollection(4) [li, li, li, li]

      // #fruits 요소의 자손 노드 중에서 태그 이름이 li인 요소 노드를 모두
      // 탐색하여 반환한다.
      const $fruits = document.getElementById('fruits');
      const $lisFromFruits = $fruits.getElementsByTagName('li');
      console.log($lisFromFruits); // HTMLCollection(3) [li, li, li]
    </script>
  </body>
</html>

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

인수로 전달한 class 값을 갖는 모든 요소들을 갖는 HTMLCollection 객체를 반환

<!DOCTYPE html>
<html>
  <body>
    <ul>
      <li class="fruit apple">Apple</li>
      <li class="fruit banana">Banana</li>
      <li class="fruit orange">Orange</li>
    </ul>
    <script>
      // class 값이 'fruit'인 요소 노드를 모두 탐색하여 HTMLCollection 객체에 담아 반환한다.
      const $elems = document.getElementsByClassName('fruit');

      // 취득한 모든 요소의 CSS color 프로퍼티 값을 변경한다.
      [...$elems].forEach(elem => { elem.style.color = 'red'; });

      // class 값이 'fruit apple'인 요소 노드를 모두 탐색하여 HTMLCollection 객체에 담아 반환한다.
      const $apples = document.getElementsByClassName('fruit apple');

      // 취득한 모든 요소 노드의 style.color 프로퍼티 값을 변경한다.
      [...$apples].forEach(elem => { elem.style.color = 'blue'; });
    </script>
  </body>
</html>
<!DOCTYPE html>
<html>
  <body>
    <ul id="fruits">
      <li class="apple">Apple</li>
      <li class="banana">Banana</li>
      <li class="orange">Orange</li>
    </ul>
    <div class="banana">Banana</div>
    <script>
      // DOM 전체에서 class 값이 'banana'인 요소 노드를 모두 탐색하여 반환한다.
      const $bananasFromDocument = document.getElementsByClassName('banana');
      console.log($bananasFromDocument); // HTMLCollection(2) [li.banana, div.banana]

      // #fruits 요소의 자손 노드 중에서 class 값이 'banana'인 요소 노드를 모두 탐색하여 반환한다.
      const $fruits = document.getElementById('fruits');
      const $bananasFromFruits = $fruits.getElementsByClassName('banana');

      console.log($bananasFromFruits); // HTMLCollection [li.banana]
    </script>
  </body>
</html>

class값을 갖는 요소가 존재하지 않는경우 getElementsByClassName 메서드는 빈 HTMLCollection객체를 반환.

39.2.4 CSS 선택자를 이용한 요소 노드 취득

/* 전체 선택자: 모든 요소를 선택 */
* { ... }
/* 태그 선택자: 모든 p 태그 요소를 모두 선택 */
p { ... }
/* id 선택자: id 값이 'foo'인 요소를 모두 선택 */
#foo { ... }
/* class 선택자: class 값이 'foo'인 요소를 모두 선택 */
.foo { ... }
/* 어트리뷰트 선택자: input 요소 중에 type 어트리뷰트 값이 'text'인 요소를 모두 선택 */
input[type=text] { ... }
/* 후손 선택자: div 요소의 후손 요소 중 p 요소를 모두 선택 */
div p { ... }
/* 자식 선택자: div 요소의 자식 요소 중 p 요소를 모두 선택 */
div > p { ... }
/* 인접 형제 선택자: p 요소의 형제 요소 중에 p 요소 바로 뒤에 위치하는 ul 요소를 선택 */
p + ul { ... }
/* 일반 형제 선택자: p 요소의 형제 요소 중에 p 요소 뒤에 위치하는 ul 요소를 모두 선택 */
p ~ ul { ... }
/* 가상 클래스 선택자: hover 상태인 a 요소를 모두 선택 */
a:hover { ... }
/* 가상 요소 선택자: p 요소의 콘텐츠의 앞에 위치하는 공간을 선택
   일반적으로 content 프로퍼티와 함께 사용된다. */
p::before { ... }
  • 인수로 전달한 css선택자를 만족시키는 요소 노드가 여러개인 경우 첫번째 요소노드만.
  • 인수로 전달된 css선택자를 만족시키는 요소 노드가 존재하지 않는 경우 null반환
  • 인수로 전달한 css선택자가 문법에 맞지 않는 경우 DOMException발생.
<!DOCTYPE html>
<html>
  <body>
    <ul>
      <li class="apple">Apple</li>
      <li class="banana">Banana</li>
      <li class="orange">Orange</li>
    </ul>
    <script>
      // class 어트리뷰트 값이 'banana'인 첫 번째 요소 노드를 탐색하여 반환한다.
      const $elem = document.querySelector('.banana');

      // 취득한 요소 노드의 style.color 프로퍼티 값을 변경한다.
      $elem.style.color = 'red';
    </script>
  </body>
</html>
// 모든 요소 노드를 탐색하여 반환한다.
const $all = document.querySelectorAll('*');
// -> NodeList(8) [html, head, body, ul, li#apple, li#banana, li#orange, script]

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

<!DOCTYPE html>
<html>
  <body>
    <ul id="fruits">
      <li class="apple">Apple</li>
      <li class="banana">Banana</li>
      <li class="orange">Orange</li>
    </ul>
  </body>
  <script>
    const $apple = document.querySelector('.apple');

    // $apple 노드는 '#fruits > li.apple'로 취득할 수 있다.
    console.log($apple.matches('#fruits > li.apple'));  // true

    // $apple 노드는 '#fruits > li.banana'로 취득할 수 없다.
    console.log($apple.matches('#fruits > li.banana')); // false
  </script>
</html>

39.2.6 HTMLCollection 과 NodeList

<!DOCTYPE html>
<head>
  <style>
    .red { color: red; }
    .blue { color: blue; }
  </style>
</head>
<html>
  <body>
    <ul id="fruits">
      <li class="red">Apple</li>
      <li class="red">Banana</li>
      <li class="red">Orange</li>
    </ul>
    <script>
      // class 값이 'red'인 요소 노드를 모두 탐색하여 HTMLCollection 객체에 담아 반환한다.
      const $elems = document.getElementsByClassName('red');
      // 이 시점에 HTMLCollection 객체에는 3개의 요소 노드가 담겨 있다.
      console.log($elems); // HTMLCollection(3) [li.red, li.red, li.red]

      // HTMLCollection 객체의 모든 요소의 class 값을 'blue'로 변경한다.
      for (let i = 0; i < $elems.length; i++) {
        $elems[i].className = 'blue';
      }

      // HTMLCollection 객체의 요소가 3개에서 1개로 변경되었다.
      console.log($elems); // HTMLCollection(1) [li.red]
    </script>
  </body>
</html>

HTMLCollection 객체는 실시간으로 노드객체의 상태를 변경하는 살아있는 DOM컬렉션 객체.

위와 같은 이유르 역방향으로 순회하면 이런 문제를 회피할 수 있다.

// for 문을 역방향으로 순회
for (let i = $elems.length - 1; i >= 0; i--) {
  $elems[i].className = 'blue';
}
// while 문으로 HTMLCollection에 요소가 남아 있지 않을 때까지 무한 반복
let i = 0;
while ($elems.length > i) {
  $elems[i].className = 'blue';
}

유사배열객체면서 이터러블인 HTMLCollection을 배열로 바꾸고 순회하면 이런 문제를 해결 (forEach,map,filter,reduce)

// 유사 배열 객체이면서 이터러블인 HTMLCollection을 배열로 변환하여 순회
[...$elems].forEach(elem => elem.className = 'blue');

NodeList

  • 실시간으로 객체의 상태 변경을 반영하지 않는 객체
  • NodeList.prototype.forEach 메서드를 상속 받아 사용할 수 있음
  • 예외로, childNodes 프로퍼티가 반환하는 NodeList 객체는 HTMLCollection과 같이 상태가 실시간으로 반영

노드 객체의 상태 변경과 상관없이 사용하려면 HTMLCollection이나 NodeList객체를 배열로 변환해서 사용권장.

두객체는 모두 유사배열이면서 이터러블
=> 스프레드 문법으로 배열 변환 o.

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

    // childNodes 프로퍼티는 NodeList 객체(live)를 반환한다.
    const { childNodes } = $fruits;
    console.log(childNodes instanceof NodeList); // true

    // $fruits 요소의 자식 노드는 공백 텍스트 노드(39.3.1절 "공백 텍스트 노드" 참고)를 포함해 모두 5개다.
    console.log(childNodes); // NodeList(5) [text, li, text, li, text]

    for (let i = 0; i < childNodes.length; i++) {
      // removeChild 메서드는 $fruits 요소의 자식 노드를 DOM에서 삭제한다.
      // (39.6.9절 "노드 삭제" 참고)
      // removeChild 메서드가 호출될 때마다 NodeList 객체인 childNodes가 실시간으로 변경된다.
      // 따라서 첫 번째, 세 번째 다섯 번째 요소만 삭제된다.
      $fruits.removeChild(childNodes[i]);
    }

    // 예상과 다르게 $fruits 요소의 모든 자식 노드가 삭제되지 않는다.
    console.log(childNodes); // NodeList(2) [li, li]
  </script>
</html>

3 노드 탐색

  • DOM 트리 상의 노드를 탐색 할 수 있도록 Node, Element 인터스페이스는 트리 탐색 프로퍼티를 제공
  • Node.prototype 이 제공하는 프로퍼티
  • parentNode : 부모 노드 탐색, (부모 노드는 텍스트 노드가 될 수 X)
  • previousSibling : 이전 형제 노드 탐색하여 반환, 요소 노드 또는 텍스트 노드를 반환
  • firstChild : 첫 번째 자식 노드 반환 , 요소 노드 또 는 텍스트 노드
  • childNodes : 자식 노드를 모두 탐색 하여 NodeList로 반환, 텍스트 노드 포함 될 수 있음
  • Element.prototype 이 제공하는 프로퍼티
  • previousElementSibling : 이전 형제 노드 반환, 요소 노드만 반환
  • nextElementSibling : 자신의 다음 형제 요소 노드 반환, 요소 노드만 반환
  • children : 자식 노드 중에서 요소 노드만 모두 탐색하여 HTMLCollection 으로 반환 (텍스트 노드 포함 x)

39.4 노드 정보 취득

Node.prototype.nodeType

  • 노드 객체의 종류. 즉, 노드 타입을 나타내는 상수를 반환
  • 노드 타입 상수는 Node에 정의되어 있음
  • Node.ELEMENT_NODE: 요소 노드 타입을 나타내는 상수 1을 반환
  • Node.TEXT_NODE: 텍스트 노드 타입을 나타내는 상수 3을 반환
  • Node.DOCUMENT_NODE: 문서 노드 타입을 나타내는 상수 9를 반환

Node.prototype.nodeName

  • 노드의 이름을 문자열로 반환
  • 요소 노드: 대문자 문자열로 태그 이름("UL", "LI" 등)을 반환
  • 텍스트 노트: 문자열 "#text"를 반환
  • 문서 노드: 문자열 "#document"를 반환

39.5 요소 노드의 텍스트 조작

39.5.1 nodevalue

  • 노드 객체의 값(텍스트 노드의 텍스트)을 반환
  • 문서 노드나 요소 노드는 nodeValue 참조하면 null 반환
<!DOCTYPE html>
<html>
  <body>
    <div id="foo">Hello</div>
  </body>
  <script>
 <-- 1. #foo 요소 노드의 자식 노드인 텍스트 노드를 취득한다. -->
    const $textNode = document.getElementById('foo').firstChild;
 
<-- 2. nodeValue 프로퍼티를 사용하여 텍스트 노드의 값을 변경한다. -->
    $textNode.nodeValue = 'World'; 
  </script>
</html>

39.5.2

  • 요소 노드의 텍스트와 자손 노드의 텍스트를 모두 취득
  • 즉, textContent는 요소노드의 콘텐츠 영역(시작 태그와 종료태그 사이)의 모든 텍스트를 모두 반환
  • 이때 HTML 마크업은 무시됨

39.6 DOM조작

  • 새로운 노드를 DOM에 추가하거나 기존 노드를 삭제 , 교체 등 조작가능.

39.6.1 innerHTML

  • 요소 노드의 콘텐츠 영역 사이에 포함된 모든 HTML 마크업을 문자열로 반환
  • innerHTML 프로퍼티에 문자열을 할당하면 요소노드의 모든 자식노드가 제거되고 할당한 문자열의 파싱되어 DOM에 반영
<!DOCTYPE html>
<html>
  <body>
    <ul id="fruits">
      <li class="apple">Apple</li>
    </ul>
  </body>
  <script>
    const $fruits = document.getElementById('fruits');
    //<-- 노드 추가 --> 
    $fruits.innerHTML += '<li class="banana">Banana</li>';
 
    //<-- 노드 교체 --> 
    $fruits.innerHTML = '<li class="orange">Orange</li>';
 
   // <-- 노드 삭제 --> 
    $fruits.innerHTML = '';
  </script>
</html>

단점

  • 크로스 사이트 스크립트 공격에 취약
  • 모든 자식요소를 제거하고 할당하기 때문에 비효율적
  • 새로운 요소를 삽입할 때 위치를 지정할 수 없음


HTML 새니티제이션

HTML 새니티제이션
크로스사이트 스크립팅 공격을 예방하기 위해 잠재적 위험을 제거하는 기능. DOMPurify 라이브러리를 사용하는 걸 권장.

DOMPurify.sanitize(`<img src="x" onerror="alert(document.cookie)">`);

39.6.2 insertAdjacentHTML

  • 기존 요소를 제거하지 않으면서 위치를 지정해 새로운 요소를 삽입
  • 첫 번재 인수로 위치를 지정 (beforebegin, afterbegin, beforend, afterend)
<!DOCTYPE html>
<html>
  <body>
    <!-- beforebegin -->
    <div id="foo">
      <!-- afterbegin -->
      text
      <!-- beforeend -->
    </div>
    <!-- afterend -->
  </body>
  <script>
    const $foo = document.getElementById('foo');

    $foo.insertAdjacentHTML('beforebegin', '<p>beforebegin</p>');
    $foo.insertAdjacentHTML('afterbegin', '<p>afterbegin</p>');
    $foo.insertAdjacentHTML('beforeend', '<p>beforeend</p>');
    $foo.insertAdjacentHTML('afterend', '<p>afterend</p>');
  </script>
</html>

39.6.3 노드 생성과 추가

요소 노드 생성

  • Document.prototype.createElement(tagName) 메서드는 요소 노드를 생성하여 반환
  • tagName 인수에는 태그 이름을 나타내는 문자열을 전달
  • createElement 메서드로 생성한 요소 노드는 기존 DOM에 추가되지 않고 홀로 존재하는 상태로, 이후에 DOM에 추가하는 처리가 필요
  • createElement메서드로 생성한 요소 노드는 아무런 자식 노드가 없는 상태

텍스트 노드 생성

Document.prototype.createTextNode(text) 메서드는 텍스트 노드를 생성하여 반환
createTextNode 메서드로 생성한 텍스트 노드는 요소 노드의 자식 노드에 추가되지 않고 홀로 존재하는 상태로, 이후에 요소 노드에 추가하는 처리가 필요

텍스트 노드를 요소 노드의 자식 노드로 추가

  • Node.prototype.appendChild(childNode) 메서드는 인수로 전달한 노드를 메서드를 호출한 노드의 마지막 자식 노드로 추가
  • childNode 인수에는 추가할 자식 노드를 전달
  • 요소 노드에 자식 노드가 하나도 없는 경우에는 textContent 프로퍼티를 사용하여 텍스트 노드를 추가하는 것이 더욱 간편
  • 요소 노드에 자식 노드가 있는 경우textContent 프로퍼티에 문자열을 할당하면 요소 노드의 모든 자식 노드가 제거되고 할당한 문자열이 텍스트로 추가되므로 주의

39.7 어트리 뷰트

  • HTML 문서가 파싱 될 때 어티리뷰트는 어티리뷰트 노드로 변환 되어 요소 노드와 연결 됨
  • 하나의 어트리뷰트당 하나의 어트리뷰트 노드 생성
  • 이때 모든 어트리뷰트 노드의 참조는 유사 배열 객체이자 이터러블인 NamedNodeMap 객체에 담겨서 요소 노드의 attributes 프로퍼티에 저장

HTML 어트리뷰트 조작

  • Element.prototype.getAttirbute(attributeName) : 어트리뷰트 값을 참조
  • Element.prototype.setAttirbute(attributeName, attributeValue) : 어트리뷰트 값을 변경
  • Element.prototype.hasAttirbute(attributeName) : 어트리뷰트 존재하는지 확인
  • Element.prototype.removeAttirbute(attributeName) : 특정 어트리뷰트 삭제

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

  • 요소 노드 객체에는 HTML 어트리뷰트에 대응 하는 DOM 프로퍼티가 존재
  • 즉, HTML 어트리 뷰트는 중복 관리 되는 것처럼 보인다.
  • 요소 노드의 attributes 프로퍼티에서 관리하는 어트리뷰트 노드
  • 요소 노드의 DOM 프로퍼티

차이점 구분

  • HTML 어트리뷰트의 역할을 HTML 요소의 초기상태를 지정, 초기 상태를 의미하며 변하지 않음
  • 요소 노드는 상태(state)를 가지고 있다.
  • 요소 노드는 2개이상의 상태(초기 상태 와 최신 상태)를 관리해야한다.
  • 요소 노드의 초기 상태는 어트리뷰트 노드가 관리
  • 요소 노드의 최신 상태는 DOM 프로퍼티가 관리

어트리뷰트 노드

  • HTML 어트리뷰트로 지정한 초기상태는 어트리뷰트 노드에서 관리
  • 초기 상태 값을 취득하거나 변경 하려면 getAttribute / setAttribute 메서드를 사용

DOM 프로퍼티

  • 사용자가 입력한 최신 상태를 관리
  • 단 사용자 입력에 의한 상태 변화와 관계있는 DOM 프로퍼티만 최신 상태 값을 관리( ex- input)
  • getAttribute 메서드로 취득한 값은 언제나 문자열 이지만, DOM 프로퍼티로 취득한 최신 상태값은 문자열이 아닐 수 있다.

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

data 어티리뷰트와 dataset 프로퍼티를 사용해 어트리뷰트와 자바스크립트 간에 데이터를 교환 가능
data 어트리뷰트는 data- 접두사 뒤에 임의의 이름을 붙여 사용
data 어트리뷰트 값은 HTMLElement.dataset 프로퍼티로 취득
존재 하지 않는 이름을 키로 dataset 프로퍼티에 할당하면 HTML 요소에 data 어트리뷰트가 추가


39.8 스타일

39.8.1 인라인 스타일 조작

  • HTMLElement.prototype.style 프로퍼티
  • getter / setter 가 모두 존재하는 접근자 프로퍼티로 요소 노드의 인라인 스타일을 취득하거나 추가 또는 변경
<!DOCTYPE html>
<html>
<body>
  <div style="color: red">Hello World</div>
  <script>
    const $div = document.querySelector('div');
 
    <-- 인라인 스타일 취득 -->
    console.log($div.style); // CSSStyleDeclaration { 0: "color", ... }
 
    <-- 인라인 스타일 변경 -->
    $div.style.color = 'blue';
 
    <-- 인라인 스타일 추가 -->
    $div.style.width = '100px';
    $div.style.height = '100px';
    $div.style.backgroundColor = 'yellow';
  </script>
</body>
</html>

39.8.2 클래스 조작

  • class 어트리뷰트에 대응하는 DOM 프로퍼티는 class 가 아니라 className 과 classList

className

Element.prototype.className
class 어트리뷰트의 값을 문자열로 반환
클래스 값이 공백으로 구분되어 있을 경우 그대로 문자열로 반환
classList

Element.prototype.classList

class 어트리뷰트의 정보를 담은 DOMTokenList 객체를 반환
DOMTokenList 객체는 class 어트리뷰트의 정보를나타내는 컬렉션 객체로 유사 배열이면서 이터블
DOMTokenList 주요 메서드
add(... className) : 인수로 전달된 1개의 이상의 문자열을 class 어트리뷰트 값으로 추가
remove(... className) : 인수로 전달한 1개 이상의 문자열과 일치하는 class 어트리뷰트에서 삭제 (일치 하는 클래스가 없으면 무시됨)
item(index) : 인수로 전달한 index에 해당하는 클래스를 class 어트리뷰트에서 반환
contains(className) : 인수로 전달한 문자열과 일치하는 클래스가 class 어트리뷰트에 포함되어 있는지 확인
replace(oldClassName, newClassName) : 첫 번째 인수 클래스를 두번째 클래스로 변경
toggle(className[, force]) : 인수로 전달한 문자열과 일치하는 클래스가 존재하면 제거하고 존재하지 않으면 추가

profile
step by step

0개의 댓글