DOM

신유빈·2023년 3월 9일
0
post-thumbnail

노드

HTML 요소와 노드 객체

<div class = "greeting"> Hello </div>

HTML 요소노드기록내용
시작태그div 요소 노드div
어트리뷰트 이름class어트리뷰트 노드class = "greeting"
어트리뷰트 값greeting어트리뷰트 노드class = "greeting"
콘텐츠Hello텍스트노드"Hello"
종료태그/div 요소 노드div


분류기능
HTML 요소HTML 문서를 구성하는 개별적인 요소를 의미합니다.
*콘텐츠 영역 안엔 텍스트뿐만 아니라 다른 HTML 요소도 포함될 수 있습니다.

*콘텐츠영역 : 시작태그와 종료태그 사이
노드 객체HTML 요소 간에는 중첩되면서 부자관계가 생깁니다.
그 부자관계를 반영하여 HTML 요소를 객체처럼 만든 뒤 각각 노드 객체로 만듭니다.
그리고 그 노드객체들을 트리 구조로 구성합니다.


이렇게 노드 객체들로 구성된 *트리 자료구조를 DOM 이라고 합니다.
(Document Object Model)

(위 그림에는 공백 텍스트 노드가 생략되어있습니다)

* 트리자료구조





노드의 종류

1. 문서노드 document node

문서노드는 document 객체를 가르킵니다.
window.document 또는 document로 참조할 수 있습니다.
DOM 트리의 최상위에 존재하는 루트 노드이기에 요소, 어트리뷰트 , 텍스트에 접근하려면 무조건 문서노드를 통해야 합니다.

2. 요소 노드 element node

요소 노드는 HTML 요소를 가르키는 객체입니다.
문서의 구조를 표현합니다.

3. 어트리뷰트 노드 attribute node

어트리뷰트 노드는 HTML 요소의 어트리뷰트를 가르키는 객체입니다.
어트리뷰트 노드는 요소노드에만 연결되어있고, 부모노드에 연결되어 있지 않기때문에 무조건 요소노드에 먼저 접근한 후 참조할 수 있습니다.

4. 텍스트노드 text node

텍스트노드는 HTML 요소의 텍스트를 가르키는 객체입니다.
요소노드가 문서의 구조를 표현한다면, 텍스트노드는 문서의 정보를 표현한다고 할 수 있습니다.
텍스트노드는 요소노드의 자식 노드입니다. 자식을 가질 수 없습니다.
텍스트노드에 접근하려면 부모인 요소노드에게 먼저 접근해야합니다.


4가지 노드 타입 외에도 주석을 위한 Comment 노드, DOCTYPE을 위한 DocumentType 노드, 복수의 노드를 생성하여 추가할 때 사용하는 DocumentFragment 노드 등 총 12개의 노드 타입이 있다.
DocumentFragment 노드에 대해서는 39.6.4절 "복수의 노드 생성과 추가에서 자세히 살펴보자.


노드객체의 상속구조

모든 노드 객체는 object, EventTarget, Node 인터페이스를 상속받습니다.

분류기능
EventTarget 인터페이스이벤트 관련 기능 addEventListener, removeEventListener 등
Node 인터페이스트리 탐색 기능 : Node.parentNode, Node.childNodes, Node.previousSibling, Node.nextSibling
노드정보제공 기능 : Node.nodeType, Node.nodeName

추가적으로,

문서노드 는 Document, HTMLDocument 인터페이스를 상속받고,
어트리뷰트 노드 는 Attr,
텍스트노드 는 CharacterData 인터페이스를 상속받습니다.
요소 노드 는 Element 인터페이스를 상속받습니다.

분류기능
HTML Element 인터페이스style 프로퍼티 등 HTML요소가 공통적으로 갖는 기능
HTMLInputElement 인터페이스value 프로퍼티 등 HTML요소가 고유하게 갖는 기능


DOM은
1. 지금까지 살펴본 바와 같이 HTML 문서의 계층적 구조와 정보를 표현해줍니다.
2. 노드 객체의 종류,타입에 따라 필요한 기능을 프로퍼티와 메서드의 집합인 DOM API로 제공합니다.

DOM API를 쓰면 HTML 구조나, 내용, 스타일 등을 동적으로 조작할 수 있습니다.

DOM API

  1. 요소노드 취득
  2. 노드 탐색
  3. 노드 정보 취득
  4. 요소노드의 텍스트 조작
  5. DOM 조작
  6. 어트리뷰트
  7. 스타일

1. 요소 노드 취득

	document.getElementById('id')
	document.getElementsByTagName('li') 
	document.getElementsByClassName('class') 
	document.querySelector('#선택자')
	document.querySelectorAll('.선택자')
	Element.matches('.선택자')

 	document.getElementById('id')
  • 인수로 전달한 요소를 하나의 요소 노드로 반환합니다.

  • 만약 인수로 전달된 요소가 존재하지 않는 경우 null을 반환합니다.


     	document.getElementsByTagName('li') 
  • * 을 넣으면 모든 HTML 태그를 선택합니다.

  • 만약 인수로 전달된 요소가 존재하지 않는 경우 빈 HTMCollection을 반환합니다.


    	document.getElementsByClassName('class') 
  • 인수로 전달한 요소를 HTMCollection으로 반환합니다.

  • 만약 인수로 전달된 요소가 존재하지 않는 경우 빈 HTMCollection을 반환합니다.


    	document.querySelector('#선택자') 
  • 인수로 전달된 css 선택자를 만족하는 요소가 여러개면 첫번째 요소 노드만 반환합니다.


    	document.querySelectorAll('.선택자')
  • 인수로 * 을 넣으면 모든 HTML 문서노드를 전달합니다.

  • 여러개의 노드 객체를 갖는 NodeList 객체를 반환합니다. (이터러블)

  • 인수로 전달된 css 선택자를 만족시키는 요소가 없으면 빈 NodeList객체를 반환합니다.

  • 인수로 전달된 css 선택자가 문법에 맞지 않는 경우 DOMException 에러가 발생합니다.


    	Element.matches('.선택자')
  • css선택자로 특정 요소 노드를 취득할 수 있는지 확인한다. 이벤트 위임을 사용할때 유용하다.


    HTMLCollection

  • getElementsByClassName ,getElementsByTagName 이 반환합니다.

  • 실시간으로 상태가 바뀌어서 반복문을 돌릴때 요소가 제거되기도 합니다.


    NodeList

  • querySelectorAll 이 반환합니다.
    대부분 실시간으로 상태가 바뀌지 않아 반복문을 돌릴때 요소가 제거되지 않습니다.

  • 배열만큼 다양하지는 않지만 forEach, item, entries, key, values 메서드를 제공합니다.


    HTMLCollection , NodeList 공통점

  • for..of로 순회할 수 있습니다.

  • 둘다 스프레드문법 Array.from 메서드로 해체가 가능해서 배열로 바꿔서 사용하는게 좋습니다.

  • 노드객체의 상태 변경과 상관없이 안전하게 쓸 수 있기 때문입니다.

  • 배열로 변환하면 유용한 고차함수를 쓸 수 있어서 좋습니다. (forEach, map, filter, reduce 등)

    Array.from(boldtext);
    var strong = [...document.getElementsByTagName("strong")];

    css 선택자 문법을 사용하는 querySelector getElementBy00 보다 다소 느립니다. 하지만 좀 더 구체적인 조건으로 요소 노드를 취득할 수 있는 장점이 있습니다.
    그래서 id가 있는 경우엔 getElementById('id')를 쓰고
    그 외의 경우엔 querySelector(),querySelectorAll() 방식을 쓰는 걸 권장합니다.



2. 노드 탐색

요소 노드를 취득한 다음, 그 요소 노드 기준으로 부모, 형제, 자식을 찾고 싶을 때가 있습니다.

분류프로퍼티키기능
Node.prototypeparentNode
previousSibling
firstChild
childNodes
(이름에 노드가 들어가있습니다.)
NodeList 에 담아 반환합니다.
요소 노드텍스트노드를 함께 보내줍니다.
Element.protypepreviousElementSibling
nextElementSibling
children
(이름에 element가 들어가 있습니다.)
HTMLCollection 에 담아 반환합니다.
요소 노드만 반환합니다. (텍스트 요소는 반환하지 않습니다.)

노드 탐색 프로퍼티는 모두 접근자 프로퍼티입니다.
단 노드탐색 프로퍼티는 읽기 전용으로 setter없이 getter만 있기 때문에 수정이 불가능합니다.

  1. 자식 탐색

     Node.childNodes
     Element.children
    
     Node.firstChild
     Node.lastChild
    
     Element.firstElementChild
     Element.lastElementChild
    
     Node.hasChildNodes
  2. 부모탐색 - 부모가 텍스트노드인 경우는 없기 때문에 하나만 있다.

    	Node.parentNode
  3. 형제탐색

    	Node.previousSibling
    	Node.nextSibling
    	
    	Element.previousElementSibling
    	Element.nextElementSibling

3. 노드 정보 취득

분류기능반환
Node.nodeType노드 객체의 종류를 상수로 반환합니다. 요소 노드이면 1,
텍스트노드이면 3,
문서노드이면 9
Node.nodeName노드 이름을 문자열로 반환합니다. 요소 노드이면 대문자 문자열로 UL,Li 를 반환합니다.
텍스트노드이면 문자열 "#text" 를 반환합니다.
문서노드이면 문자열 "#document"를 반환합니다.

4. 요소 노드 의 텍스트 조작

 nodeValue
 textContent

nodeValue

지금까지 살펴본 노드 탐색, 노드정보 프로퍼티는 모두 읽기 전용 접근자 프로퍼티입니다.
지금부터 살펴볼 Node.nodeValue 프로퍼티는 setter와 getter가 모두 존재하는 접근자 프로퍼티입니다.

따라서 nodeValue 프로퍼티는 참조와 할당이 모두 가능합니다.

 <body>
   <div id="요소">Hello</div>
   <script>
     //document는 nodeValue를 가지고 있지 않다.
     console.log(document.nodeValue); //null

     //요소노드 자체는 nodeValue를 가지고 있지 않다.
     const 요소노드 = document.getElementById("요소");
     console.log(요소노드.nodeValue); //null

     //요소노드의 firstChild 인 텍스트노드는 nodeValue를 가지고있다.
     const 텍스트노드 = 요소노드.firstChild;
     console.log(텍스트노드.nodeValue); //Hello
   </script>
 </body>

이처럼 텍스트노드의 nodeValue를 참조할때만 텍스트노드의 값인 텍스트를 반환합니다.
텍스트노드가 아닌 노드객체를 참조하면 null을 반환합니다.

텍스트노드의 nodeValue 프로퍼티에 값을 할당하면 텍스트를 변경할 수 있다.

 <body>
   <div id="요소">Hello</div>
   <script>
	  // 요소노드를 취득한 다음, 요소노드의 자식인 텍스트노드를 탐색한다.
     // 텍스트노드는 요소노드의 자식이므로 firstChild 프로퍼티로 탐색할 수 있다.
     
     const 요소노드 = document.getElementById("요소");
     const 텍스트노드 = 요소노드.firstChild;
     
  	  텍스트노드.nodeValue = "안녕" 
     
     console.log(텍스트노드.nodeValue);	// 안녕
   </script>
 </body>


textContent

Node.textContent 프로퍼티는 setter와 getter가 모두 존재하는 접근자 프로퍼티입니다.
요소노드의 텍스트와 자손노드의 텍스트를 모두 취득하거나 변경합니다.

요소노드의 textContent 프로퍼티를 참조하면 요소노드의 *콘텐츠 영역 내의 텍스트를 모두 반환합니다. 다시 말해, 요소노드의 childNodes 프로퍼티가 반환한 모든 노드들의 텍스트 노드의 값, 즉 텍스트를 모두 반환합니다. 이때, HTML 마크업은 무시됩니다.

*콘텐츠영역 : 시작태그와 종료태그 사이

 <body>
   <div id="요소">Hello <span>world!</span></div>
   <script>
     console.log(document.getElementById("요소").textContent);
     // Hello world!
   </script>
 </body>

요소노드의 textContent 프로퍼티에 문자열을 할당하면 요소노드의 모든 자식 노드가 제거되고, 할당한 문자열이 텍스트로 취급됩니다. 이때, 할당한 문자열에 HTML마크업이 포함되어있어도 파싱해주지 않고 문자열 그대로 입력해줍니다.

<body>
  <div id="요소">Hello <span>world!</span></div>
  <script>
		document.getElementById("요소").textContent = "Hi<span>there!</span>"
  </script>
</body>

참고로 textContent 프로퍼티와 유사한 동작을 하는 innerText 도 있습니다.
다만 innerText 프로퍼티는 다음과 같은 이유로 사용하지 않는 것이 좋습니다.

  • innerText 프로퍼티는 CSS에 순종적입니다. CSS에 의해 숨겨진 요소노드의 텍스트는 반환하지 않습니다.
  • innerText 프로퍼티는 CSS를 고려하기 때문에 textContent 프로퍼티보다 느립니다.
 	innerText 			
    // 와~ 자바스크립트 너무 쉽다! 

렌더링 후의 모습을 인식할 수 있습니다. display:none으로 가리면 안보임.
HTMLElement 인터페이스 의 속성입니다.

	textContent		
   // 와~ 자바스크립트 너무 쉽다! 뻥이에요ㅜㅜ

숨겨져있는 텍스트 까지 가져옵니다.
Node 인터페이스의 속성입니다.

	innerHTML 
	// 와~ 자바스크립트 너무 쉽다! <span style = "display:none">뻥이에요ㅜㅜ</span>


nodeValue 프로퍼티도 텍스트를 참조할 수 있었지만, textContent보다 코드가 더 복잡합니다.

분류과정
nodeValue요소노드 선택 -> 텍스트노드선택-> 텍스트노드의 nodeValue까지 찾아야 값을 반환해줌.
textContent요소노드 선택 -> 바로 텍스트 값을 반환해줌


DOM 조작

DOM 조작은
1. 새로운 노드를 생성하여 DOM에 추가하거나
2. 기존 노드를 삭제,
3. 또는 교체하는 것을 말합니다.

DOM 조작에 의해 새로운 노드가 추가되거나 삭제되면 *리플로우와 리페인트가 발생하기에 성능에 영향을 줍니다. 따라서, 복잡한 콘텐츠를 다루는 DOM 조작은 성능 최적화를 위해 주의해서 다루어야합니다.

*리플로우와 리페인트
DOM 요소를 조작하거나, 브라우저 크기를 조절하는 경우 스타일이 다시 계산되기도 합니다.(viewport 변경) 이럴 때 Reflow와 Repaint가 발생합니다.
만약 스타일이나 DOM 내부를 변경하는 DOM API가 사용됐다면, 우리의 DOM은 뭔가 변경됐음을 감지하고, 다시 위의 브라우저 작동 과정을 반복하고, 리렌더링을 진행합니다.
이 과정에서 리플로우와 리페인트가 발생합니다.
https://velog.io/@young_pallete/Reflow-Repaint%EC%9D%84-%EC%95%8C%EC%95%84%EB%B3%B4%EC%9E%90

innerHTML

Element.prototype.innerHTML 프로퍼티는 setter와 getter가 모두 존재하는 접근자 프로퍼티로서 요소노드의 HTML 마크업을 취득하거나 변경합니다.
요소 노드의 innerHTML 프로퍼티를 참조하면 요소노드의 콘텐츠 영역내의 포함된 모든 HTML 마크업을 문자열로 반환합니다.

앞서 살펴본 textContent 프로퍼티를 참조하면 HTML 마크업을 무시하고 텍스트만 반환하지만, innerHTML 프로퍼티는 HTML 마크업이 포함된 문자열을 그대로 반환합니다.

요소노드의 innerHTML 프로퍼티에 문자열을 할당하면
요소노드의 모든 자식노드가 제거되고
할당한 문자열에 포함되어있는 HTML 마크업이 파싱되어서 자식노드로 DOM에 반영됩니다.
그래서 innerHTML 프로퍼티를 사용하면 HTML 마크업 문자열로 간단히 DOM 조작이 가능합니다.

그런데 사용자에게 입력받은 데이터를 그대로 innerHTML에 입력하면 바로 HTML마크업이 파싱되어 DOM에 반영되기 때문에 크로스 사이트 스크립팅 공격에 취약하여 위험합니다.

그 안에 자바스크립트 악성코드를 심어놓으면 파싱 과정에서 그대로 실행될 수 있기 때문입니다.

  <body>
    <div id="요소">Hello</div>
    <script>
       document.getElementById('요소').innerHTML = '<script> alert(document.cookie) </script>';
       document.getElementById('요소').innerHTML = `<img src = "x" onerror="alert('님 쿠키에 숨겨둔 비밀번호는 이제 제껍니다.',document.cookie)">`
    </script>
  </body>

1) HTML5부터 inner HTML 요소로 삽입된 script 요소 내의 코드는 실행되지 않습니다.

2) 그래서 script 요소 없이 img 태그로 강제로 에러를 발생시켜서 자바스크립트 코드를 실행하게끔 공격해봤습니다.

HTML 새니티제이션
사용자로부터 입력받은 데이터에 의해 발생할 수 있는 크로스 사이트 스크립팅 공격을 예방하기 위해 사용합다. DOMPurify 라이브러리를 이용하는 것을 권장하는데, 다음과 같이 잠재적 위험을 내포한 HTML 마크업을 새니티제이션(살균)해줍니다.

DOMPurify.sanitize(`<img src='x' onerror="alert('document.cookie)">`)
// <img src='x'> 만 남겨줍니다.

두번째 단점으론 요소노드의 innerHTML 프로퍼티에 HTML 마크업 문자열을 할당하면, 모든 자식 노드들을 제거하고 자기만 파싱해서 DOM을 변경해버린다. 그래서 변경하고 싶을땐 이렇게 써야한다.

$fruits.innerHTML += $fruits.innerHTML + '<li class="banana">바나나</li>'

세번째 단점으론, 삽입 위치를 지정할 수 없다.
사과와 오렌지 사이에 뭘 넣고 싶을 수도 있는데 그럴 때는 사용할 수가 없다.
복잡하지 않은 요소를 새롭게 추가할 땐 유용할 수 있으나,
기존 요소를 제거하지 않으면서 위치를 지정해 새로운 요소를 삽입해야 할 때는 사용하지 않는 것이 좋다.

innerHTML 프로퍼티를 이용한 DOM 조작 요약

장점단점
구현이 간단하고 직관적이다.1. 크로스 사이트 스크립팅 공격에 취약하다.
2. 요소 노드 안에 있는 자식노드들을 다 지워버리고 자기만 남겨둔다.
=== 요소를 추가하고 싶을 때 비효율적이다.
3. 삽입 위치를 지정할 수 없다.

insertAdjacentHTML 메서드

Element.prototype.insertAdjacentHTML(position, DOMString) 메서드는 기존 요소를 제거하지 않으면서 위치를 지정해 새로운 요소를 삽입할 수 있습니다.

insertAdjacentHTML 메서드는 기존 요소에는 영향을 주지 않고 새롭게 삽입될 요소만을 파싱하여 자식요소로 추가해줍니다.
그래서 innerHTML 프로퍼티보다 효율적이고 빠릅니다.
다만, innerHTML 프로퍼티와 마찬가지로 HTML 마크업 문자열을 파싱하므로 크로스 스크립팅 사이트 공격에 취약합니다.

노드 생성과 추가

분류기준
Element.innerHTML
Element .insertAdjacentHTML()
HTML 마크업을 직접 넣은 후 문자열로 파싱하여 노드를 생성함
Node.createElement
Node.createTextNode
Node.appendChild
Node.insertBefore
Node.cloneNode
Node.replaceChild
Node.removeChild
노드를 직접 생성, 삽입, 삭제, 치환함
const 요소 = document.getElementById("요소");

요소.innerHTML = "<p>안녕<p>";
요소.insertAdjacentHTML("<p>안녕<p>");
document.createElement("li");
document.createTextNode("안녕");
document.createDocumentFragment(); 
  // 여러개의 노드를 한번에 추가할때 감싸는 용도로 사용     
  // const $fragment = document.createDocumentFragment();   
  // 요소.appendChild($fragment);
요소.appendChild(a); 
  // 인수로 전달한 노드를 요소의 언제나 마지막 자식 노드로 추가한다. 
  // 원래 있던 노드이면 현재 위치해서 제거하고 새로운 위치에 추가한다. 즉 이동한다.
요소.insertBefore(a, b);
  // 첫번째 인수(a)로 전달한 노드를 두번째 인수(b)로 전달한 노드 앞에 삽입한다.
  // 원래 있던 노드이면 현재 위치해서 제거하고 새로운 위치에 추가한다. 즉 이동한다.
  // b가 null 이면 appendChild처럼 동작한다. 요소의 마지막 자식노드로 추가된다.
요소.cloneNode(true | false); 
  // 노드를 복사한다. 복사하고 나서 appendchild()를 한다.
요소.replaceChild(a, b); 
  // a 노드를 b노드로 교체한다. a노드는 DOM에서 제거된다.
요소.removeChild(a); 
  // a 노드를 제거한다.

어트리뷰트

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

HTML문서의 구성요소인 HTML요소는 여러개의 어트리뷰트를 가질수 있다.
HTML어트리뷰트는 HTML요소의 동작을 제어하기 위한 추가적인 정보를 제공한다.

<input id = "아이디" class="클래스" value="밸류"/> 

<시작태그 어트리뷰트이름 = "어트리뷰트값" />

  1. 글로벌 어트리뷰트
    id, class, style, lang, tabindex, draggable, hidden 등

  2. 이벤트핸들러 어트리뷰트
    onclick, onchange, onfocus, onblur, oninput, onkeypress, onkeydown, onkeyup, onmouseover, onsubmit, onload 등

위 둘은 모든 HTML요소에 공통적으로 사용할 수 있다.

input 요소의 type, value, checked 어트리뷰트는 input 요소에만 사용할 수 있다.


HTML 문서가 파싱될 때 HTML어트리뷰트는 어트리뷰트노드로 변환되어 요소노드와 연결된다.
모든 어트리뷰트 노드의 참조는 NameNodeMap 객체에 담겨서 요소노드의 attributes 프로퍼티에 저장된다.

따라서 요소노드의 모든 어트리뷰트노드는 요소노드의 Element.prototype.attributes 프로퍼티로 취득할 수 있다.
attributes 프로퍼티는 getter만 존재하는 읽기 전용 접근자 프로퍼티이며, 요소노드의 모든 어트리뷰트노드의 참조가 담긴 NameNodeMap 객체를 반환한다.

 <body>
   <input id="인풋" type="텍스트" value="밸류" />
   <script>
	  const 인풋 = document.getElementById("인풋");
      console.log(인풋.attributes);
      console.log(인풋.attributes.id.value);
      console.log(인풋.attributes.type.value);
      console.log(인풋.attributes.value.value);
   </script>
 </body>

HTML 어트리뷰트 조작

Element.prototype.getAttribute();
Element.prototype.setAttribute();
Element.prototype.hasAttribute();
Element.prototype.removeAttribute();

위에서 살펴본 attributes 프로퍼티는 읽기만 가능하기 때문에 값의 취득은 가능하지만 변경은 불가능하다.
또한 attributes.id.value 이렇게 길게 써야해서 불편하다.

Element.prototype.getAttribute(attributeName)
메서드를 쓰면 값을 참조할 수 있다.
Element.prototype.setAttribute(attributeName, attributeValue)
메서드를 쓰면 값을 변경할 수 있다.
Element.prototype.hasAttribute(attributeName);
메서드를 쓰면 값이 존재하는지 확인할 수 있다.
Element.prototype.removeAttribute(attributeName);
메서드를 쓰면 값을 삭제할 수 있다.

 <body>
   <input id="인풋" type="텍스트" value="밸류" />
   <script>
	  const 인풋 = document.getElementById("인풋");
     
      인풋.getAttribute("value");
      인풋.setAttribute("value", "발루");
      console.log("value가 있니?", 인풋.hasAttribute("value"));
      인풋.removeAttribute("value");
      console.log("value가 있니?", 인풋.hasAttribute("value"));      
   </script>
 </body>

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

요소노드는 상태(state)를 가지고 있다.

input으로 예를 들면,
웹페이지를 처음 표시하거나 새로고침할때 나타나는 초기 상태
사용자가 입력 필드에 값을 입력했을때 나타는 최신 상태

이처럼 요소노드는 2개의 상태를 관리해야하기 때문에
초기 상태는 HTML어트리뷰트가 관리하고,
최신 상태는 DOM프로퍼티가 관리한다.

어트리뷰트 노드
HTML 어트리뷰트로 지정한 HTML의 요소의 초기상태는 어트리뷰트 노드에서 관리한다.
이 값은 사용자가 입력해서 상태가 변경되어도 변하지 않고 초기에 지정한 상태를 그대로 유지한다.
어트리뷰트 노드가 관리하는 초기 상태값을 취득하거나 변경할때 getAttribute(), setAttribute() 를 이용한다.

DOM 프로퍼티
사용자가 입력한 최신 상태는 요소노드의 DOM 프로퍼티가 관리한다.
DOM 프로퍼티에 값을 할당하는 것은 사용자가 입력한것과 동일한 작용을 한다.
input의 value프로퍼티, checkbox의 checked 프로퍼티가 그런 역할을 한다.

 <body>
   <input id="인풋" type="text" value="" />
   <script>
     const 인풋 = document.getElementById("인풋");
     인풋.value = "값을 입력하는 중~"
   </script>
 </body>

다만, 모든 프로퍼티가 상태를 관리하는건 아니기 때문에 id 어트리뷰트랑 id 프로퍼티값은 항상 같다. 이처럼 사용자 입력에 의한 상태변화와 관계있는 DOM 프로퍼티만 최신 상태 값을 관리하고 그렇지 않은 어트리뷰트와 DOM 프로퍼티는 항상 동일한 값으로 연동한다.

HTML 어트리뷰트DOM 프로퍼티
HTMl 요소의 초기상태를 지정한다.사용자가 입력하는 최신상태에 따라 동적으로 변경된다.

HTML 어트리뷰트와 DOM 프로퍼티의 대응 관계

대부분의 HTML 어트리뷰트는 HTML 어트리뷰트 이름과 동일한 DOM 프로퍼티와 1:1로 대응한다. 단, 다음과 같이 HTML 어트리뷰트와 DOM 프로퍼티가 언제나 1:1로 대응하는 것은 아니며, HTML 어트리뷰트 이름과 DOM 프로퍼티 키가 반드시 일치하는 것도 아니다.

  • id 어트리뷰트와 id 프로퍼티는 1:1 대응하며, 동일한 값으로 연동한다.
  • input 요소의 value 어트리뷰트는 value 프로퍼티와 1:1 대응한다. 하지만 value 어트리뷰트는 초기 상태를, value 프로퍼티 는 최신 상태를 갖는다.
  • class 어트리뷰트는 className, classList 프로퍼티와 대응한다.
  • for 어트리뷰트는 *htmlFor 프로퍼티와 1:1 대응한다.
  • td 요소의 colspan 어트리뷰트는 대응하는 프로퍼티가 존재하지 않는다.
  • textContent 프로퍼티는 대응하는 어트리뷰트가 존재하지 않는다.

    어트리뷰트 이름은 대소문자를 구별하지 않지만 대응하는 프로퍼티 키는 카멜 케이스를 따른다(maxlength→ maxLength).

    * htmlFor에 input의 아이디나 네임을 적어 인풋과 연결합니다. 라벨은 input의 이름을 적는 태그입니다.

0개의 댓글