본문 바로가기

JavaScript, HTML, CSS

[HTML, 코드스테이츠]02. DOM

코드 스테이츠 Pre 코스 일곱째 주 수강 후기.

 CSS는 신기하긴 했지만 썩 재밌진 않았는데 DOM은 진짜 재미있었다. 내가 짠 코드로 HTML을 제어하니까 재밌네.

 수업 전 트위틀러를 만들었을 땐 클로저를 사용해서 innerHTML로 코드를 짰었다. 근데 저번 화요일 수업에서 그걸 만들어 주는 메서드가 있다는 것을 배웠다. 완전 신세계ㅋㅋㅋㅋ 근데 목요일 수업에서는 그 편한 메서드보다 템플릿이 더 좋다는 걸 배웠음. 템플릿을 사용한다면 js를 보지 않고도 디자인을 바꿀 수 있다! 많은 걸 배워서 좋았다.

 


DOM

  • DOM(Document Object Model)
    • HTML 또는 XML document와 상호작용하고 표현하는 API
    • HTML 문서의 구조와 관계를 객체(Object)로 표현한 모델.
    • DOM은 기본적으로 정의되어 있지 않고 브라우저가 JavaScript 구현을 시작했을 때 나타남.
    • JS에서 document라는 전역 변수로 접근이 가능하다.
    • browser에서 로드되며, 노드 트리(각 노드는 document의 부분을 나타냄)로 표현하는 document 모델이다.
      • 노드들은 생성, 이동 및 변경될 수 있고 이벤트 리스너를 노드에 추가해 주어진 이벤트가 발생할 때 트리거 되게 할 수 있다.

=> DOM: JavaScript에서 HTML 등의 엘리먼트 속성 값을 얻어내고, 변경하는 방법


크롬 개발자 도구(F12 or Ctrl+Shift+I)에서 엘리먼트를 확인하는 방법

 

1. Elements창에서 확인하고 싶은 태그를 선택(클릭)하면 그 태그가 $0로 지정된다.

   - 지금 이 창에서도 해 볼 수 있다.

   - 콘솔 창에 typeof $0 (typeof: 뒤에 오는 변수의 타입을 반환)을 입력해 보면 $0이 Object라는 것을 알 수 있다.

2. 콘솔 창에 console.log($0)를 입력하면 현재 선택된 태그($0)를 내용을 볼 수 있다.

3. 콘솔 창에 console.dir($0)를 입력하면 현재 선택된 태그($0)의 속성(property)들을 볼 수 있다.

 

$0에 대한 설명

$0에 담긴 속성들

$0의 속성들


element와 node 비교

엘리먼트는 화면 상 보이는 것들(div, input, button)만 들어있는 반면, 노드는 엘리먼트의 내용들과 HTML상의 text도 포함되어 있다.

엘리먼트와 노드 설명을 위한 예제


데이터 속성

.html

<div data-user="ram">
  Ram T
</div>

 

.js

console.log($0.dataset.user); //'ram'

 

* js에서 데이터 속성을 추가하거나 변경할 수 있다.

 

.js

$0.dataset.user = 'R';
$0.dataset.userId = '1'; //dataset.userId라고 쓰면 HTML상에서 data-user-id가 됨.
//마찬가지로 dataset.tmpTmpTmp도 HTML상에서는 data-tmp-tmp-tmp가 됨.
$0.dataset.name = 'ram';

위 코드를 실행하면 html의 내용이 아래와 같이 바뀐다.

 

.html

<div data-user="R" data-user-id="1" data-name="ram">
  Ram T
</div>

이벤트: 어떤 사용자의 입력이나 다른 트리거에 의해 발생하는 메시지로, 이에 대한 핸들러(리스너)를 추가할 수 있다.

이벤트의 속성 이름들: onclick, onmouseover, onkeyup 등

 

클릭 이벤트(해당 태그를 클릭했을 경우 발생하는 이벤트)에 기능 추가하기

 

.html

<button>등록</button>

 

.js

$0.onclick = function() {
  console.log('등록버튼 클릭');
}

 

위 코드를 실행했을 경우의 결과

.js

//.onclick말고도 아래와 같이 메소드를 이용해 구현할 수도 있음
$0.addEventListener('click', function() {
  console.log('등록버튼 클릭');
});

 

 

[MDN] DOM의 이벤트들(여기의 이벤트명을 그대로 사용하려면 addEventListener를 사용해야 함)

 


엘리먼트 선택: js를 이용하여 특정 엘리먼트를 선택하고 가져올 수 있음

 

1. 태그를 이용: getElementByTagName

let allDiv = document.getElementsByTagName('div');

현 HTML상의 모든 div를 가져와서 allDiv에 저장

 

2. id를 이용: getElementById

let newComment = document.getElementById('new-comment');

id가 new-comment인 엘리먼트를 newComment에 저장

 

3. class를 이용: getElementsByClassName, querySelectorAll

let comments = document.getElementsByClassName('comment');

class가 comment인 엘리먼트들을 comments에 저장

 

4. selector를 이용: querySelector / querySelectorAll

   - 이것만 알고 있어도 됨

let newComment = document.querySelector('#new-comment'); //new-comment는 id라서 '#new-comment'
let comments = document.querySelectorAll('.comment'); //comment는 class라서 '.comment'

newComment에는 id가 new-comment인 엘리먼트 저장 / comments에는 class가 comment인 엘리먼트들 저장

위의 데이터 조작이나 이벤트 핸들러 등도 이것을 응용해서 할 수 있다.


DOM조작

1. innerHTML: 읽기, 쓰기 가능

   - HTML 태그를 입력할 수 있음.

   - 가장 쓰기 쉬운 속성이지만, 느리고 보안 위협이 있음(textContent가 안전함)

 

.html

<div id="target">전</div>

 

.js

let target = document.querySelector('#target');
target.innerHTML = '<span>후</span>';

 

.js이후의 .html

<div id="target">
  <span>후</span>
</div>

 

 

2. 메소드: 반드시 알고 있어야 함

생성과 동시에 이벤트 핸들러의 등록이 가능하다.

 

.html

<div id="target">전</div>

 

.js

let target = document.querySelector('#target');
let newSpan = document.creatElement('SPAN'); //span엘리먼트 생성
newSpan.innerHTML = '후';
target.appendChild(newSpan); //target에 newSpan을 자식 엘리먼트로 추가(아랫쪽부터 추가)

 

.js이후의 .html

<div id="target">
  전
  <span>후</span>
</div>

 

* 삭제도 가능

let target = document.querySelector('#target');
target.remove();

 

 

3. <template> 태그

HTML 내에 HTML의 조각의 정의함. <template> 태그는 다른 곳에 붙여 넣기 전까지는 화면에 보이지 않음.

메소드를 사용하는 것보다 깔끔한 구현을 할 수 있다.

HTML과 JS의 구분이 철저하기 때문에 JS를 모르는 디자이너들도 <template>을 보고 CSS를 변경할 수 있음.

 

.html

<template id="template">
  <span>템플릿</span>
</template>

<div id="target">전</div>

 

.js

let target = document.querySelector('#target');
let template = document.querySelector('#template');

//#template의 내용을 깊은 복사(자식 노드를 전부 포함한 복사)
let newContent = document.importNode(template.content, true);
newContent.querySelector('span').textContent = '후';
//복사된 newContent내부에서 가장 먼저 발견된 span의 내용을 '후'로 바꿈

target.innerHTML = ''; //target 내부의 html 비움
target.appendChild(newContent);

 

.js이후의 .html

<template id="template">
  <span>템플릿</span>
</template>

<div id="target">
  <span>후</span>
</div>