본문 바로가기
매일코딩/자바스크립트 개념

[자바스크립트 기초]DOM 문서객체모델의 이해1

by 인생여희 2017. 2. 24.
반응형


문서 객체 모델은 브라우저가 HTML 페이지의 모델을 생성하고 이 페이지가 브라우저 창에 보여지는 동안 자바스크립트를 이용하여 웹페이지의 내용에 접근하고 수정하기 위한 방법을 명시하고 있다.

 

HTML 페이지에 대한 모델 구성하기

브라우저는 웹 페이지를 로드한 후 , 이 페이지에 대한 모델을 메모리에 생성한다.

 

HTML 페이지에 접근하고 수정하기

DOM은 모델 내의 각 객체에 접근하고 내용을 수정하기 위한 속성과 메서드들을 정의하고 있다. 내용을 수정하면 브라우저에서 사용자가 보게 될 내용이 변경된다.

 

DOM은 브라우저가 DOM트리를 이용하여 이 모델을 구성하는 방법을 명시한다.

DOM이 객체 모델이라고 불리는 이유는 모델이 객체를 이용하여 구성되기 때문이다.

 

웹 페이지에 대한 모델로서의 DOM 트리

브라우저는 웹 페이지를 로드할 때 해당 페이지에 대한 모델을 생성한다. 이 모델을 DOM트리라고 브르며, 이 모델은 브라우저의 메모리에 저장된다.

또한, 이 모델은 네 종류의 노드로 구성된다.


문서노드

위의 코드는 쇼핑 목록을 작성한 HTML 코드이다. 이코드에 대한 DOM트리는 다음 페이지에 표시되어 있다. 각 요소, 특성, HTML 내의 문자열들은 모두 각자의 DOM 노드 로 표현된다.

트리의 최상위에는 문서 노드가 존재하며, 이 노드는 전체 페이지를 표현한다.(또한 브라우저 내에 document 객체로 구현되어 있다.)

 

요소나 특성, 텍스트 노드에 접근하려면 문서 노드를 통해야만 한다. 따라서 DOM 트리를 조회하기 위한 시작점 역할을 한다고 생각하면 된다.

 

요소노드

HTML 요소들은 HTML 페이지의 구조를 서술한다.(<h1>부터 <h6> 까지의 요소들은 머리글을 표현하며, <p>태그는 텍스트 문단의 시작과 끝을 표현한다.)

DOM트리에 접근하려면 일단 요소를 탐색해야 한다. 원하는 요소를 찾은 후에야 비로소 필요에 따라 그 요소의 텍스트와 특성 노드에 접근할 수 있다. 그렇기 때문에 텍스트나 특성에 접근하여 값을 변경하는 방법을 학습하기 전에 요소(element)노드에 접근하는 메서드들을 먼저 학습해야 한다.

 

특성노드

HTML 요소의 여는 태그에는 특성을 지정할 수 있으며, 이런 특성들은 DOM 트리 내에서 특성 노드로 표현된다.

특성 노드는 해당 특성이 지정된 요소의 자식노드가 아니라 해당요소의 일부로서 표현된다. 일단, 요소에 한번 접근하면 해당 요소의 특성을 읽거나 수정할 수 있는 자바스크립트 메서드 및 속성을 사용할 수 있다. 예를 들어, 요소의 외관을 바꾸기 위해 새로운 CSS 규칙을 적용하려는 목적으로 class 특성 값을 변경하는 것은 이제 보편적인 작업이다.

 

텍스트 노드

일단, 요소 노드에 접근하면 해동 요소 내부의 텍스트에 접근할 수 있다. 이 텍스트는 해당 요소의 텍스트 노드에 저장된다. 텍스트 노드는 자식 노드를 가질 수 없다.

 

각각의 노드는 메서드와 속성을 가진 객체이다.

스크립트는 DOM트리에 접근하여 그 내용을 수정한다.

DOM트리에 가해진 모든 변경 사항은 브라우저에 반영된다.

 

DOM트리 활용하기

DOM트리에 접근하고 수정하는 작업은 크게 두 단계로 나뉜다.

 

1.작업을 수행할 대상 요소를 표현하는 노드를 찾는다.

2. 해당 노드의 텍스트나 자식 요소, 특성 등을 조작한다.

 

1단계: 요소에 접근하기


하나의 요소 노드를 선택하기

getElementById() -요소의 id특성 값을 이용한다.

querySelector() - css 선택자를 이용하며, 일치하는 요소들 중 첫 번째 요소를 리턴한다.

 

여러 개의 노드 선택하기

getElementByClassName() - 지정된 class 특성 값을 가지는 요소들을 모두 선택한다.

 

getElementByTagName() - 지정된 태그 이름을 가지는 요소들을 모두 선택한다.

 

querySelectorAll() - 지정된 css 선택자와 일치하는 요소드를 모두 선택한다.

 

요소 노드 사이를 탐색하기 한 요소로부터 연관된 다른 요소로 이동할 수 있다.


parentNode 현재 요소 노드의 부모 노드를 선택한다.(단 하나의 요소만 리턴한다.)

 

previousSibling / nextSibling 현재 DOM 트리 내의 이전 또는 다음 형제 요소를 선택한다.

 

firstChild / lastChild 현재 요소의 첫 번째 혹은 마지막 자식 노드를 선택한다.

 

2단계: 요소 조작하기

 

-텍스트 노드에 접근/수정하기

어느 한 요소가 가진 텍스트는 해당 요소의 텍스트 노드에 저장된다. 이 텍스트 노드에 접근하는 방법은 다음과 같다.

<li> 요소를 선택한다.

firstChild 속승을 사용하여 텍스트 노드를 선택한다.

텍스트 노드의 유일한 속성 nodeValue 속성을 이용하여 요소의 텍스트를 가져온다.

nodeValue

이 속성을 통해 텍스트 노드의 내용에 접근하거나 수정할 수 있다.

 

-HTML 내용을 조작하기

innerHTML 속성을 이용하면, 이 하나의 속성을 통해 모든 자식 요소와 텍스트 콘텐츠에 접근이 가능하다.

특정 요소의 텍스트 콘텐츠에만 접근하려면 textContent 속성을 이용한다.

아래 나열된 메서드들을 이용하면 새로운 노드를 생성하고, 노드 트리에 새로운 노드를 추가하거나 제거하는 등의 작업이 가능하다.

createElement()

createTextNode()

appendChild()/ removeChild()

이를 DOM 조작 이라고 한다.

 

-특성 값에 접근/ 수정하기

특성을 조작할 때는 다음의 속성과 메서드를 사용할 수 있다.

className /id

hasAttribute() - 지정된 특성이 존재하는지를 확인한다.

getAttribute() - 지정한 특성 값을 가져온다.

setAttribute() - 지정된 특성 값을 변경한다.

removeAttribute() - 지정된 특성을 요소로부터 제거한다.

 

 

DOM 쿼리 캐싱하기

DOM 트리에서 요소를 찾아내는 메서드들을 DOM 쿼리라고 한다.

어떤 요소를 한 번 이상 조작할 필요가 있다면 요소를 조회한 결과를 저장하기 위한 변수를 사용해야 한다.(스크립트에서 요소에 접근하거나 수정하기 위해서는 반드시 자바스크립트 해석기가 DOM트리 내에서 요소를 찾아야 한다.)


) getElementById(‘one’);

 


변수에 요소를 저장하는 것은, 실제로는 DOM 트리 내에 요소의 위치를 변수에 저장하는 것이다.

요소 노드의 속성과 메서드는 이 변수를 통해 조작이 가능하다.

) var itemOne = getElementById(‘one’);

 

이렇게 하면 브라우저가 같은 요소를 탐색하기 위해 DOM 트리를 여러번 조회하는 것을 방지 할 수 있다

이런 방법을 캐싱이라고 한다.

 


ID특성을 이용하여 요소 선택하기

<!DOCTYPE html>

<html>

<head>

<title>J</title>

<meta name="viewport" content="width=device-width, initial-scale=1.0">

<link rel="stylesheet" href="css/c05.css">

</head>

<body>

<div id="page">

<h1 id="header">식료품목록</h1>

<h2>Buy groceries</h2>

<ul>

<li id="one" class="hot"><em>fresh</em> 사과</li>

<li id="two" class="hot"></li>

<li id="three" class="hot"></li>

<li id="four">식초</li>

</ul>

</div>

<script src="js/get-element-by-id.js"></script>

</body>

</html>

 

.JS

// 요소를 선택해서 변수에 저장

var el = document.getElementById('one');

// 요소를 선택하여 변수에 저장한다.

el.className = 'cool';

 

NODELIST:

하나 이상의 요소를 리턴하는 DOM 쿼리들

DOM 메서드는 하나 이상의 요소를 리턴할 때는 NodeList 객체를 리턴한다.

 

NodeList 객체는 요소 노드의 모음이다. 각 노드에는 인덱스 번호가 부여된다.

(배열처럼 0부터 시작하는 번호이다.)

NodeList 객체에 요소 노드가 저장되는 순서는 HTML 페이지에 해당 요소가 정의된 순서를 따른다.

DOM쿼리가 NodeList 객체를 리턴하면 이를 이용하여 다음과 같은 작업을 수행할 수 있다.

 

NodeList 내에서 하나의 요소를 찾는다.

NodeList에 저장된 각 아이템에 대해 루프를 실행하여 각 요소 노드에 대해 동일한 코드를 실행한다.

 

NodeList 객체는 배열과 유사하게 보이며 동일한 방식으로 요소에 번호를 부여하지만 실제로 배열은 아니다. 이 객체는 컬렉션이라고 부르는 타입의 객체이다.

 

반드시 알아두어야할 속성과 메서드

length 속성은 NodeList 객체 내에 저장된 아이템의 개수를 리턴한다.

item() 메서드는 NodeList 객체에서 () 에 지정된 인덱스 번호에 해당하는 노드를 리턴한다.

 

Nodelist 객체에서 요소 선택하기

NodeList 객체에서 요소를 선택하는 방법은 두 가지가 있다.

item() 메서드와 배열의 요소 참조 문법이 바로 그것이다.

두 방법 모두 원하는 요소의 인덱스 번호를 필요로 한다.

 


// class 턱성 값이 hot 인 요소들을 모두 선택하여 리턴 된 nodeList 객체를 변수에 저장

var elements= document.getElementByClassName(‘hot’);

if(elements.length >= 1){

 

var firstItem = elements.item(0);

}

 

nodeList 객체는 컬랙션 내의 특정 노드를 리턴하는 item() 메서드를 제공한다.

이 메서드를 호출 할때는 괄호 내에 접근하고자 하는 노드의 인덱스 번호를 매개변수로 전달해야 한다.

 

nodeList 객체 내에 저장된 요소가 없을 때 메서드를 호출하는 것은 리소스를 낭비하는 일이다. 그래서 탐색을하기 전에 length 속성을 이용해서 nodelist 객체가 하나 이상의 노드를 저장하고 있는지 확인한다.

 

 

배열 문법은 item() 메서드 보다 빠르게 동작하기 때문에 더 보편적으로 사용된다.

var elements= document.getElementByClassName(‘hot’);

if(elements.length >= 1){

 

var firstItem = elements.item[0];

 

}

 

 

) class 특성을 이용

var elements = document.getElementsByClassName('hot'); // hot아이템을 찾는다.

 

if (elements.length > 2) { // 아이템이 세 개이상 탐색되었는 지 확인

var el = elements[2]; // nodelist객체에서 세 번째 아이템을 선택

el.className = 'cool'; // 선택된 요소의 class 특성 값을 변경한다.

 

}

 

) 태그 이름으로 요소 선택하기

var elements = document.getElementsByTagName('li'); // <li> 요소 찾는다.

 

if (elements.length > 0) {

 

var el = elements[0]; // 배열 문법을 이용하여 첫 번째 아이템을 선택

el.className = 'cool'; // 선택된 요소의 class 특성 값을 변경한다.

 

}

 

전체 nodelist를 대상으로 동작 반복하기

 

nodelist 객체를 얻어 온 후에는 이 컬렉션 내의 각 노드를 대상으로 루프를 실행할 수 있으며 그때마다 동일한 코드를 실행할 수 있다.

 

)

var hotItems = document.querySelectorAll('li.hot'); // NodeList 객체를 변수에 저장

if (hotItems.length > 0) { // 발견된 요소가 존재하면

for (var i = 0; i < hotItems.length; i++) { // 각 아이템마다 루프를 실행해라

hotItems[i].className = 'cool'; //

}

}


 


 

 

 

 

 

 

 

 

 

 

 

반응형

댓글