CodeStates/React

[DOM] Document Object Model

디스페어 2022. 2. 14.

문서 객체 모델 DOM(Document Object Model)

1. DOM의 개념

HTML 요소를 Object(JavaScript Object)처럼 조작(Manipulation)할 수 있는 Model
  • HTML의 구조와 관계를 객체로 표현한 모델로 document라는 전역변수를 통해 HTML에 접근 가능
  • 자바스크립트를 이용해 DOM에 접근하여 엘리먼트의 속성값을 얻거나 변경할 수 있음

 

2. DOM의 구조

  • 자바스크립트의 객체와 같이 트리 구조이기 때문에 자바스크립트의 DOM이 브라우저에 접근하기 가장 용이
    *다른 언어도 DOM을 가지고 있지만 자바스크립트가 가장 안정적

 

3. console.dir()로 콘솔에서 엘리먼트 조회하기

  • console.log(document): html문서 형식으로 보여줌
  • console.dir(document): 객체의 형태로 보여줌
    *자바스크립트로 접근할 수 있는 key와 value를 조회할 수 있기에 더 용이

 

 

DOM으로 HTML 요소 분석하기

1. .tagName

  • 태그 이름 조회 가능

 

2. .id

  • id 조회 가능

 

3. class

3-1 .className

  • className 조회 가능(문자열로 출력)

 

3-2. .classList

  • class 목록 조회 가능(유사 배열로 출력)
  • classList[idx]로 조회 가능

 

4. .attibute

  • 속성 객체 조회 가능

 

5. .style

  • 스타일 객체 조회 가능

 

6. .innerHTML, .innerText, .textContent

  • 엘리먼트에 담긴 내용 조회 가능
  • innerHTML, textContent: 값을 할당하여 내용까지 변경 가능
  • innerHTML: 태그까지 모두 함께 보여줌(html형식), 태그까지 적용하여 변경 가능
    *보안상 해킹에 노출될 문제를 가지고 있어 지양(xss공격)
  • textContent: 실제 포함되어 있는 공백까지 적용되어 보여줌, 내용만 변경 가능
  • innerText: 화면에 렌더링되고 있는 텍스트를 보여줌

 

7. .value

function getInputValue() {
  let elUsername = document.querySelector("#username") //input 태그
  console.log(elUsername.value) //input 창에 사용자가 입력한 내용 조회
}

let registerBtn = document.querySelector(".register")
registerBtn.addEventListener("click", getInputValue) 
//등록버튼을 누르면 input 창에 사용자가 입력한 내용을 가져옴
//함수이름만 적는 것 주의

registerBtn.onclick = getInputValue
//위와 동일
  • value: 사용자가 form에 입력한 값을 의미
  • form 입력 값 조회 가능
    *form 입력 창: input태그 등

 

8. .parentElement: 부모 엘리먼트 조회

let newsContents = document.body.children[1]
console.log(newsContents.parentElement)
  • document.body.children[1]의 부모 엘리먼트 조회

 

9. .children: 자식 엘리먼트 조회

console.log(document.body.children)
  • 가지고있는 자식 태그 조회 가능

 

10. .childNodes

  • 자식 노드 조회 가능
    *node: 태그뿐 아니라 자식 태그가 가지고있는 textContent까지 포함
Node: 태그 노드와 텍스트 노드, 공백 노드 등 노드 전체을 의미하며 Element의 상위 개념으로 DOM 관련 객체는 대부분 Node에서 파생
Element: Node의 기능을 적용(implements)한 객체 타입으로 텍스트 노드를 제외하고, 흔히 생각하는 태그만을 의미

 

11. .dataset

  • date-* 속성에 담긴 값 조회 가능
  • HTML문서에서, 화면에 보이지 않지만 태그 자체에 데이터를 심어놓고싶을 때 용이

 

 

DOM으로 HTML 조작하기

1. createElement

document.createElement('div')

새로운 div태그 element를 생성한 후 변수에 할당

 

2. append / appendChild

function appendNewTweet() {
  let li = document.createElement('li')
  li.textContent = "대충 리스트라는 글"
  let tweetContainer = document.querySelector('#tweetContainer')
  
  tweetContainer.appendChild(li)
}
  • createElement로 생성한 li는 아무것과도 연결이 안된 상태이므로 트리 구조에 연결 필요
  • 원하는 부모 엘리먼트인 #tweetContainer에 appendChild
  • append: 마지막 자식으로 들어감, 자바스크립트 메소드로 한번에 여러개의 자식 설정 가능
    *문자열 노드를 추가로 지원함
  • appendChild: 마지막 자식으로 들어감, DOM 메소드로 한번에 하나의 자식만 설정 가능
    *노드 객체만 가능
  • prependChild: 첫번째 자식으로 올림

 

3. querySelector / querySelectorAll

document.querySelector('.tweet')
document.querySelectorAll('.tweet')
  • 셀렉터: HTML 태그("div"), id("#tweetList"), class(.tweet)
  • querySelector: 클래스 이름이 tweet인 HTML 엘리먼트를 조회
    *oneTweet엔 최상단 엘리먼트 하나만 존재
  • querySelectorAll: 클래스 이름이 tweet인 모든 HTML 엘리먼트를 조회
    *oneTweet엔 모든 해당 엘리먼트 존재, 배열처럼 for문 사용 가능
  • getElementsByTagName / getElementById / getElementsByClassName으로도 조회 가능

 

4. textContent / classList.add / setAttribute

4-1. textContent

document.querySelector('.tweet').textContent = 'dev';
tweetDiv.textContent = 'dev';
  • querySelector로 위치 지정 후 textContent로 문자열('dev')을 삽입
  • querySelector로 지정한 경로를 담은 변수를 선언해주면 더욱 간편
  • 기존에 textContent가 없었다면 새롭게 추가, 있었다면 교체

 

4-2. classList.add

document.querySelector('.tweet').classList.add('tweet')
tweetDiv.classList.add('tweet')
  • classList.add를 이용해 'tweet' 클래스를 추가
    *.classList.remove('tweet')를 하면 'tweet' 클래스 삭제

 

4-3. setAttribute

let sominElement = document.createElement('span')
sominElement.setAttribute('id', 'hope')
sominElement.textContent = 'I love hope'
  • 새로운 span태그 sominElement 생성
  • setAttribute를 활용하여 id를 "hope"로 지정
  • textContent를 활용하여 sominElement에 문자열('I love hope')를 삽입

 

5. remove / removeChild

document.querySelector('.tweet').remove()
tweetDiv.remove() 
//tweetDiv를 삭제

document.querySelector('#container').innerHTML = '';
//id가 container인 엘리먼트의 모든 자식 엘리먼트 삭제
//innerHTML의 사용은 지양

while (container.firstChild) {
  container.removeChild(container.firstChild);
}
//container의 첫 번째 자식 엘리먼트가 존재하면, 첫 번째 자식 엘리먼트를 제거
//결과적으로 id가 container인 엘리먼트 아래의 모든 엘리먼트 삭제

while (container.children.length > 1) {
  container.removeChild(container.lastChild);
}
//container의 자식 엘리먼트가 1개만 남을 때까지, 마지막 자식 엘리먼트를 제거


document.querySelectorAll('.tweet').forEach(function(tweet){
  tweet.remove();
})
//클래스 이름이 tweet인 엘리먼트만 찾아서 제거

for (let tweet of document.querySelectorAll('.tweet')){
  tweet.remove()
}
//클래스 이름이 tweet인 엘리먼트만 찾아서 제거
  • classList.remove(): 필요에 따라 제거/삽입 가능
  • remove(): 영구 삭제

 

 

HTML에 자바스크립트 적용하기

1. 적용 방법

<script src="script.js"></script>
  • script 태그 이용

 

2. script 태그

웹브라우저는 script 태그를 만나면 HTML 해석을 멈추고 script 요소를 실행
*script 요소는 등장과 함께 실행

 

2-1. head 태그 안쪽에 삽입

  • body를 만나기 전 script 태그를 먼저 만나기 때문에 HTML 해석을 멈추고 script 요소를 실행
  • HTML 해석이 멈췄기 때문에 자바스크립트에서 document.querySelector를 사용한 경우 콘솔에 null이 출력
    *DOM 트리가 생성되기전에 자바스크립트가 존재하지 않는 DOM 요소에 접근하게 됨
  • HTML문서는 하향식으로 읽기 때문에 script 태그를 읽느라 body를 읽지 못해 Display에 표시되는 것이 지연

 

2-2. body 태그가 끝나기 전에 삽입

  • body 내부를 모두 읽은 후 script 태그를 만나 script 요소를 실행
  • 자바스크립트에서 document.querySelector를 사용한 경우에도 DOM 요소가 모두 존재하기에 정상적으로 출력
  • head 태그 안쪽에 삽입하는 방법보다 지향
  • HTML을 모두 읽은 뒤에 script 요소를 실행하기 때문에 html의 코드가 자바스크립트에 의존적이라면 사용자에게 의미 없는 Display를 노출하게 됨

 

 

References

script 태그 적용 위치
innerHTML
append() 와 appendChild()

반응형

'CodeStates > React' 카테고리의 다른 글

[React] State & Props  (0) 2022.02.21
[React] Single-Page Application  (0) 2022.02.21
[React] React 기초와 프로젝트 시작방법  (0) 2022.02.16
[CSS] Cascading Style Sheets  (0) 2021.12.20
[HTML] HyperText Markup Language  (0) 2021.12.20

댓글