From 8872af2a11d676a9cb5c83128ca90f15fd082eb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B3=A0=EC=84=B8=EC=A2=85?= Date: Wed, 17 Jan 2024 20:45:09 +0900 Subject: [PATCH] =?UTF-8?q?docs:=20=EC=8A=A4=ED=84=B0=EB=94=9439.2.4=20~?= =?UTF-8?q?=2039.2.6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../\352\263\240\354\204\270\354\242\205.md" | 92 +++++++++++++++++++ 1 file changed, 92 insertions(+) diff --git "a/docs/39_DOM/\352\263\240\354\204\270\354\242\205.md" "b/docs/39_DOM/\352\263\240\354\204\270\354\242\205.md" index 03dca407..80637c86 100644 --- "a/docs/39_DOM/\352\263\240\354\204\270\354\242\205.md" +++ "b/docs/39_DOM/\352\263\240\354\204\270\354\242\205.md" @@ -62,3 +62,95 @@ document 객체는 브라우저가 렌더링한 HTML 문서 전체를 가르키 DOM은 HTML 문서의 계층적 구조와 정보를 표현하는 것은 물론 노드 객체의 종류, 즉 노드 타입에 따라 필요한 기능을 프로퍼티와 메서드의 집합인 DOM API로 제공한다.
이 DOM API를 통해 HTML의 구조나 내용 또는 스타일 등을 동적으로 조작할 수 있다. + +--- + +## 요소 노드 취득 + +우선 자바스크립트 등을 이용해 HTML을 동적으로 조작하기 위해선 요소 노드를 취득해야 한다. + +노드에 접근하는 방법에 대해서 알아보자. + +### id를 이용한 요소 노드 취득 + +`Document.prototpye.getElementById` 메서드는 인수로 전달한 id 어트리뷰트 값을 갖는 하나의 요소 노드를 반환한다. + +```html +
I'm div
+ +``` + +id 값은 HTML 문서 내에서 유일한 값이어야 하며, class 어트리뷰트와는 달리 공백 문자로 구분하여 여러개의 값을 가질 수 없다.
+만약 같은 id값으 갖는 요소들이 여러개라도 `getElementById` 메서드는 첫 번째 요소 노드만 반환한다. + +HTML 요소에 id 속성을 부여하면 id 값과 동일한 이름의 전역 변수가 암묵적으로 선언되고 해당 노드 객체가 할당되는 부수 효과가 있다. + +### 태그 이름을 이용한 요소 노드 취득 + +`Document.prototype/Element.prototype.getElementsByTagName` 메서드는 인수로 전달한 태그 이름을 갖는 모든 요소들을 반환한다.
이때 반환된 값은 DOM 컬렉션 객체인 `HTMLCollection` 객체를 반환한다. + +> HTMLCollection 객체는 유사 배열 객체이면서 이터러블이다. + +### class를 이용한 요소 노드 취득 + +`Document.prototype/Element.prototype.getElementsByClassName` 메서드는 인수로 전달한 class 어트리뷰트 값을 갖는 모든 요소 노드들을 반환한다.
+인수로 전달할 class값은 공백으로 구분하여 여러개의 class를 지정할 수 있다. + +### CSS 선택자를 이용한 요소 노드 취득 + +CSS 선택자는 스타일을 적용하고자 하는 HTML 요소를 특정할 때 사용하는 문법이다. + +`Document.prototype/Element.prototype.querySelector` 메서드는 인수로 전달한 CSS 선택자를 만족시키는 하나의 요소 노드를 탐색하여 반환한다. + +`Document.prototype/Element.prototype.querySelectorAll` 메서드는 인수로 전달한 CSS 선택자를 만족시키는 모든 요소 노드를 D +OM 컬렉션 객체인 NodeList객체로 반환한다. + +> `querySelector, querySelectorAll` 메서드는 `getElementById, getElementBy***` 메서드보다 다소 느린것으로 알려져있다.
id 어트리뷰트가 있는 요소 노드를 취득하는 경우에는 `getElementById` 메서드를 사용하고, 그 외에는 `querySelector, querySelectorAll` 메서드를 사용하자. + +### HTMLCollection과 NodeList + +HTMLCollection과 NodeList는 모두 유사 배열 객체이면서 이터러블이다. + +이 두가지 객체의 중요한 특징은 노드 객체의 상태 변화를 실시간으로 반영하는 살아있는 객체라는 것이다.
+HTMLCollection은 언제나 live객체로 동작하는 반면 NodeList는 대부분의 경우 non-live 객체로 동작한다. + +> NodeList도 경우에 따라 live 객체로 동작한다. + +### HTMLCollection + +`getElementsByTagNAme, getElementByClassName` 메서드가 반환하는 HTMLCollection 객체는 노드 객체의 상태 변화를 실시간으로 반영한다. + +```html + +``` + +위 ul 태그중 li 태그들의 class를 전부 'blue'로 변경해보자. + +```javascript +const $elmes = document.getElementsByClassName('red'); +for (let i = 0; i < $elems.length; i++) { + $elems[i].className = 'blue'; +} +``` + +위 코드의 동작 결과로 `apple, banana, orange` 3개의 li태그 모두 blue로 변경될것을 예상할 수 있지만 `banana` li태그는 변경되지 않는다. + +그 이유는 HTMLCollection이 live 객체라는 점에 있다.
+첫번째 li태그인 `apple` 태그의 class가 blue로 변경되는 순간 $elems에는 재할당이 이루어 지며 $elems는 apple을 제외한 banana, orange 두개의 태그가 들어가고, for 문의 i는 이미 증가된 상태가 된다. + +따라서, banana li 태그는 변경되지 않았기에 재할당이 이루어지지 않아 orange li 태그는 blue로 변경된다. + +이런 문제를 예방하기 위해서는 배열의 고차함수를 사용하는것이 좋다. + +### NodeList + +HTMLCollection 객체의 부작용을 해결하기 위해 `querySelectorAll` 메서드를 사용하는 방법도 있다.
+NodeList는 non-live 객체이기 때문에 이런 부작용을 예방해 주지만 `childNode` 프로퍼티가 반환되는 NodeList 객체는 HTMLCollection 객체와 같이 실시간으로 노드 객체의 상태 변경을 반영하는 live 객체로 동작하므로 주의가 필요하다. + +**따라서 이렇게 예상과 다른 동작을 피하고 예방하기 위해선 노드 객체의 상태 변경과 상관없이 안전하게 DOM 컬렉션을 사용하려면 HTMLCollection이나 NodeList 객체를 배열로 변환하여 사용하는 것을 권장한다.**