Javascript DOM
DOM(Document Object Model) 이란 HTML 요소를 Javascript의 Object처럼 조작할 수 있는 모델을 의미한다. 우리가 사용하는 일반적인 웹 페이지들은 모두 HTML로 구성되어 있다.
DOM은 프로그래밍 언어가 아니다. HTML은 기본적으로 트리구조를 띄고 있기 때문에, 부모 노드에서 자식 노드까지 접근하기 위해서는 Javascript로 접근할 수 있어야 한다. 정확히 말하면 DOM을 통해 javascript가 HTML 로 구성된 웹 페이지의 각 노드에 접근이 가능한 것이다.
렌더링
웹 브라우저는 HTML 소스를 받아서 각 노드를 파싱하고 사용자에게 렌더링 하는 과정을 거친다. 이 때 <script> 태그를 만나면 렌더링 과정을 일시중지 하고, Javascript 코드를 실행하게 된다.
Javascript가 DOM을 활용해 HTML 노드에 접근하기 위해서는 모든 노드가 렌더링이 되어 있는 상황이어야 한다. 따라서 <script> 태그는 <body>태그가 끝나기 직전에 위치해야 Javascript에서 정상적으로 DOM을 활용할 수 있다.
DOM CRUD
Javascript로 DOM에 접근해서 CRUD(Create, Retrieve, Update, Delete) 로직을 구성할 수 있다.
CREATE
새로운 Element를 생성한다. 새로 생성한 Element는 어떤 노드에도 연결되지 않고 붕 떠있는 상황이다. 이제 부모노드의 자식노드로 생성한 Element를 연결해줘야 한다.
const newElement = document.createElement('div');
새로 생성한 Element를 <body> 태그에 연결한다.
document.body.append('newElement');
부모 노드에 Element를 추가하는 메소드는 append()와 appendChild() 두가지가 있다. append vs appendChild 차이점은 추가할 객체의 수와 타입에 있다.
append()
부모 노드에 여러개의 태그를 삽입할 수 있다.
document.body.append('div','span', 'h1');
ul 태그를 선택하고, <div>, <span>, <h1> 태그를 한번에 삽입했다. 결과를 보면 3개의 태그가 자식 태그로 삽입되었다. append() 메소드는 Node 객체 뿐만 아니라 일반 텍스트도 자식노드로 추가가 가능하다.
appendChild()
오직 한개의 Node 객체만 추가가 가능하다. Text는 추가가 불가능하다.
Text를 추가할 경우 에러가 발생한다.
여러개의 자식 노드를 추가하면 가장 앞에 있는 Node 객체 1개만 반영된다.
Retrieve
DOM에서 특정 Node 객체를 조회하기 위해서 querySelector() 나 getElementByID() 메소드를 사용한다. 객체를 조회하기 위해서는 셀렉터를 매개변수로 전달해줘야 한다.
매개변수로는 id("#node"), class(".node") 그리고 태그("div")가 가장 많이 사용된다.
const el1 = document.querySelector('div');
const el2 = document.querySelector('#node');
const el3 = document.querySelector('.node');
id는 DOM에서 유일값이기 때문에 항상 1개의 객체를 선택하지만 class의 경우 복수사용이 가능하기 때문에 querySelectorAll() 메소드를 사용해 객체를 선택한다.
이 경우 배열의 형태로 Node 객체를 선택한다. 이렇게 반환된 객체들의 집합은 정확히는 배열이 아니다. 유사 배열객체가 반환된다. 유사 배열객체 또한 For문으로 iterable 하기 때문에 forEach나 for문 반복문을 사용할 수 있다.
const els = document.querySelectorAll('.node');
els.forEach((items)=>{
console.log(items);
})
UPDATE
querySelector() 메소드로 Node 객체를 검색후 문자열을 입력하거나 클래스 속성을 추가하면서 UPDATE 로직을 구성할 수 있다.
태그 내에 새로운 텍스트를 설정하기 위해서는 Node 객체의 textContent 속성을 사용한다. 뿐만 아니라 Node 객체의 value 값을 조절하기 위해서 아래 선택지가 있다.
const el = document.querySelector("div");
el.textContent = 'hello world';
① innerHTML
② innerText
③ textContent
Node 객체에 클래스를 추가하기 위해서는 classList 속성을 사용한다. Node 객체의 classList 프로퍼티를 살펴보면 DOMTokenList 객체를 상속받고 있다. [[Prototype]] 내부 슬롯을 보면 add, contain, forEach 등의 함수를 상속받고 있는데, 새로운 클래스를 사용할 때는 add() 메소드를 사용한다.
el.classList.add('newClass');
setAttribute()
setAttribute() 메소드를 사용해서 스타일을 변경할 수 있다. 요소를 선택하면 HTMLDivElement [[Prototype]] 을 상속받는 것을 볼 수 있다. 재미있는 건 특정 Node 객체를 생성하거나 선택했을 때 "setAttribute()" 메소드는 프로퍼티로 소유하고 있지 않다.
const element = document.querySelctor('div');
element.setAttribute("style", "background-color : red;");
setAttribute()를 상위 객체에서 상속받는다는 말인데, 상속 체인을 따라가다 보면
Node 객체 -> HTMLDivElement -> HTMLElement -> Element -> Node -> EventTarget -> Object 의 프로토타입 상속 체인을 확인할 수 있다. 이 중 Element 객체가 소유하고 있는 setAttribute() 메소드를 상속받아 사용할 수 있게 되는 것이다.
DELETE
① remove() 사용
마지막으로 DELETE을 위해서는 remove 메소드 프로퍼티를 사용한다. 객체 스스로 삭제하는 remove() 메소드는 Element 객체에서 상속받아 사용한다.
const element = document.createElement("div");
const div = document.createElement("div");
const span = document.createElement("span");
document.body.append(element);
// 노드 객체 스스로를 삭제
element.remove();
// 자식 노드 삭제
element.removeChild(div, span)
② removeChild() 사용
자식 노드를 삭제하는 removeChild() 메소드는 여러개의 Node 객체를 삭제할 수 있다. removeChild()는 Element 객체가 상속받는 Node 객체의 메소드다.
③ innerHTML 사용
Node 객체의 프로퍼티 중 innerHTML 속성을 사용하면 Node 내부의 모든 HTML 소스를 삭제할 수 있다.
element.innerHTML = '';
'Programming' 카테고리의 다른 글
[Javascript] onclick VS addEventListener 차이점? (0) | 2022.05.15 |
---|---|
[Javascript] Element와 Node 차이점? (0) | 2022.05.15 |
[Javascript] prototype 이란? (0) | 2022.05.14 |
[Javascript] __proto__ 접근자 프로퍼티 이해하기 (0) | 2022.05.14 |
[Javascript] Prototype 이란? (0) | 2022.05.14 |
댓글