DOM탐색하기
페이지에 요소 노드가 존재한다면 다음 5가지 속성을 이용하여 다른 요소들을 선택할 수 있다. 이런 과정을 DOM 탐색이라고 한다.
<ul>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
parentNode – 이 속성은 부모 노드를 찾는다.
previousSibling – 이전 노드를 찾는다.
nextSibling - 다음 노드를 찾는다
firstChild - 첫 번째 자식 요소를 찾는다.
lastChild – 마지막 자식 요소를 찾는다.
(요소가 존재 하지 않을 때는 null 이 리턴된다.)
(IE를 제외한 대부분의 브라우저들은 요소 사이의 공백 문자를 텍스트로 취급하기 때문에 리턴하는 값은 브라우저에 따라 달라지게 된다.)
이전&다음 이웃 요소
.HTML
<!DOCTYPE html>
<html>
<head>
<title>JavaScript & jQuery - Chapter 5: Document Object Model - Sibling</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">List</h1>
<h2>Buy groceries</h2>
<ul><li id="one" class="hot"><em>fresh</em> figs</li>
<li id="two" class="hot">pine nuts</li>
<li id="three" class="hot">honey</li>
<li id="four">balsamic vinegar</li>
</ul>
</div>
<script src="js/sibling.js"></script>
</body>
</html>
.JS
// 기준요소를 찾고 그 이웃 요소를 찾는다.
var startItem = document.getElementById('two');
var prevItem = startItem.previousSibling;
var nextItem = startItem.nextSibling;
// 이웃 요소들의 CALSS 특성값을 변경한다.
prevItem.className = 'complete';
nextItem.className = 'cool';
첫 번째 &마지막 자식 요소
.JS
// 탐색을 시작할 요소를 천택후 그 자식요소들을 찾는다.
var startItem = document.getElementsByTagName('ul')[0];
var firstItem = startItem.firstChild;
var lastItem = startItem.lastChild;
// 요소들의 CALSS 특성값을 변경한다.
firstItem.className = 'complete';
lastItem.className = 'cool';
요소의 내용을 가져오기/수정하기
요소의 내용을 조작하는 방식은 다음의 두 가지가 있다.
1.텍스트 노드까지 탐색하기. 이 방식은 대상 요소가 다른 요소는 가지지 않고, 오직 텍스트만 가지고 있는 경우에 적합하다.
2.상위 요소 조작하기. 이 방식을 이용하면 요소의 텍스트 노드와 자식 요소들에 모두 접근이 가능하다. 따라서 요소가 텍스트 노드 및 그에 이웃하는 자식 요소들을 가지고 있는 경우에 적합하다.
텍스트 노드- 일단 어느 한 요소로부터 텍스트 노드까지 탐색을 했다면 해당 노드에 대해 유용하게 사용할 수 있는 속성이 하나 있다.
nodeValue – 노드가 가지고 있는 텍스트 값에 접근한다.
자식요소를 포함한 요소
(요소의 텍스트 노드가 아닌) 요소 노드를 직접다루는 경우, 이 요소는 다른 마크업을 포함하고 있을 수 있다. 이런 경우 텍스트 뿐만 아니라 포함된 마크업을 조회(get) 하거나 변경(set)할수 있다.
innerHTML – 텍스트와 마크업을 가져오거나 변경한다.
textContent – 텍스트만 가져오거나 변경한다.
innerText – 텍스트만 가져오거나 변경한다.
이 속성들을 이용하여 요소의 내용을 변경하면 새로 지정한 내용이 요소의 전체 내용을 덮어쓰게 된다.
nodeValue 속성을 이용하여 텍스트 노드에 접근/변경하기
텍스트 노드를 선택하면 nodeValue 속성을 이용하여 그 내용을 조회하거나 변경할 수 있다.
<li id=“one”><em>신선한</em>무화과</li>
document.getElementById(‘one’).firstChild.nextSibling.nodeValue;
<설명>
1.getElementById(‘one’)를 이용해서<li> 요소 선택한다.
2.firstChild를 이용해서 <em> 요소 선택
3.<em>요소의 nextSibling 선택해서 그 다음 이웃 요서 선택
4. 텍스트 노드를 선택하게 됐으므로 nodeValue 속성을 이용하여 해당 노드의 텍스트를 얻어 올 수 있다.
텍스트 노드에 접근/변경하기
var itemTwo = document.getElementById('two');
var elText = itemTwo.firstChild.nodeValue; // 텍스트 내용을 가져온다.
elText = elText.replace('잣', '양배추'); // 잣을 양배추로 변경한다.
itemTwo.firstChild.nodeValue = elText; // 목록아이템을 변경한다.
textContent/innerText 속성을 이용하여 텍스트에 접근 / 변경하기
textContent 속성을 이용하면 자식 요소를 포함한 상위 요소 및 그 자식 요소의 텍스트를 가져오거나 변경할 수 있다.
textContent 속성
<li id=“one”><em>신선한</em>무화과</li>
document.getElementById(‘one’).textContent;
예제에서 <li> 요소의 텍스트를 가져오려면 <li> 요소의 textContent 속성을 사용하면 된다. 이 예제의 경우 신선한 무화과 라는 텍스트를 리턴한다.
또한 이 속성을 이용하여 요소의 내용을 변경할 수 있다. 이 경우 요소의 내용 전체가 변경된다. (ie9 이하 버전에서 지원안됨)
innerText 속성을 이용해도 텍스트 내용을 가져 올 수 있지만 잘 권장하지 않는다.
브라우저 지원 – 파이어폭스 브라우저는 이 속성을 지원하지 않는다.
css 에 순종적이다.- css에 의해 숨겨진 내용은 표시되지 않는다.
성능문제 – textContent 속성 보다 느리다.
텍스트에만 접근하기
var firstItem = document.getElementById('one'); // 목록의 첫 번째 아이템을 찾는다.
var showTextContent = firstItem.textContent; // 텍스트 가져온다.
var showInnerText = firstItem.innerText; // 텍스트 가져옴
// 두 속성을 통해 가져온 값을 목록 다음에 추가한다.
var msg = '<p>textContent: ' + showTextContent + '</p>';
msg += '<p>innerText: ' + showInnerText + '</p>';
var el = document.getElementById('scriptResults');
el.innerHTML = msg;
firstItem.textContent = 'sourdough bread'; // 첫 번째 아이템 수정
HTML 콘텐츠 추가/ 제거하기
DOM 트리에 콘텐츠를 추가하거나 제거하는 방법은 크게 두가지가 있다.
하나는 innerHTML 속성을 이용하는 방법이고, 다른하나는 DOM을 조작하는 방법이다.
innerHTML 속성
보안에 취약하다. 원하는 만큼의 마크업 텍스트를 추가할 수 있다. 수정할 때 새로운 콘텐츠를 문자열로 대입하면 된다.
접근=>콘텐츠 추가하기
DOM 조작 방식은 DOM트리 내의 개별 노드를 쉽게 조작할 수 있는 방식이다.
반면, innerHTML 속성을 사용하는 방식은 전체 콘텐츠를 수정할 때 더욱 적합하다.
DOM 조작방식
DOM 조작방식은 innerHTML 속성을 이용하는 방법보다 안전하지만, 더 많은 코드를 작성해야 하며 더 느리게 동작하는 경우도 있다.
DOM 조작은 요소와 텍스트 노드를 생성하는 DOM 메서드들을 참조하여 필요한 노드를 생성한 후, 이들을 DOM트리에 덧붙이거나 DOM틀로부터 제거하는 방식이다.
텍스트 및 마크업 수정하기
// 목록의 첫 번째 아이템을 변수에 지정한다.
var firstItem = document.getElementById('one');
// 아이템의 콘텐츠를 가져온다.
var itemContent = firstItem.innerHTML;
// 첫 번째 아이템의 콘텐츠를 링크로 수정한다.
firstItem.innerHTML = '<a href=\"http://example.org\">' + itemContent + '</a>';
//콘텐츠를 문자열로 구성하여 innerHTML속성에 대입하면 브라우저는 문자열 내의 요소들을 DOM에 추가할 것이다. 이 예제의 경우는 페이지에 <a>요소가 추가된다
DOM 조작으로 요소 추가하기
다음과 같은 세 가지 방식이 있다.
1.요소를 생성한다.
createElement() 메서드
요소 노드를 생성했지만 아직 DOM 트리에 추가된 상태는 아니다.
2. 콘텐츠를 지정한다.
createTextNode() 메서드
새로운 텍스트 노드를 생성하여 마찬가지로 변수에 저장한다.
이 노드를 요소 노드에 추가하려면 appendChild() 메서드를 이용해야 한다.
이 노드는 요소에 콘텐츠를 제공하기 위한 것이다.
3. 생성된 요소를 DOM에 추가한다.
appendChild() 메서드
이제 필요한 요소들을 모두 생성했으므로 이 메서드를 이용하여 이들을 DOM 트리에 추가한다.
이 메서드를 이용하면 DOM트리에 추가하고자 하는 요소를 어떤 요소의 자식 노드로 추가할 것인지를 지정할 수 있다.
예)
// 새로운 요소를 생성하여 변수에 저장한다.
var newEl = document.createElement('li');
// 텍스트 노드를 생성한 후 변수에 저장한다.
var newText = document.createTextNode('quinoa');
// 새 요소에 새로 생성한 텍스트 노드를 추가한다.
newEl.appendChild(newText);
// 새 요소가 추가될 위치를 선정한다.
var position = document.getElementsByTagName('ul')[0];
// 새로운 요소를 해당 위치에 추가한다.
position.appendChild(newEl);
DOM 조작으로 요소 제거하기
1.제거할 요소를 변수에 저장한다.
2. 해당 요소의 부모 요소를 변수에 저장한다.
(다음으로 제거할 요소를 포함하고 있는 부모 요소를 찾아 그 요소 노드를 변수에 저장한다.
부모 요소를 찾는 가장 간단한 방법은 제거할 요소의 parentNode 속성을 이용하는 방법이다.)
3. 부모 요소로부터 요소를 제거한다.
removeChild() 메서드는 2단계에서 선택한 부모 요소에서 지정한 요소를 제거한다. removeChild() 메서드는 더 이상 필요하지 않은 요소를 전달하기 위한 하나의 매개변수를 사용한다.
예)
// 제거할 요소를 변수에 저장한다.
var removeEl = document.getElementsByTagName('li')[3];
// 제거할 요소의 부모 요소를 찾는다.
var containerEl = document.getElementsByTagName('ul')[0];
// 요소를 제거한다.
containerEl.removeChild(removeEl);
// 첫 번째 변수인 removeEl 변수는 실제로 페이지에서 제거하고자 하는 요소를 지정한다.
// 두 번째 변수인 contailnerEl 변수는 제거할 요소를 포함하고 있는 <ul> 요소를 저장한다.
특성 노드
일단, 요소 노드를 생성했으면 해당 요소의 특성 노드에 접근 또는 수정을 위해 다른 속성과 메서드를 사용할 수 있다.
특성에 접근하여 수정하려면 두 단계를 거치게 된다.
먼저 특성을 가지고 있는 요소 노드를 선택한 후 마침표를 덧붙인다.
그런후, 다음에 설명할 메서드나 속성중 하나를 이용하여 요소의 특성을 조작한다.
document.getElementById(‘one’).getAttribute(‘class’);
dom 쿼리 .은 맴버접근 연산자
메서드
getAttribute() - 특성 값을 가져온다.
hasAttribute() - 요소 노드가 지정한 특성을 가지고 있는지 검사한다.
setAttribute() - 특성에 값을 대입한다.
removeAttribute() - 요소 노드에서 지정한 특성을 제거한다.
메서드
className – class 특성 값을 가져오거나 변경한다.
id – id 특성 값을 가져오거나 변경한다.
예)
var firstItem = document.getElementById('one'); // 목록의 첫 번째 아이템가져온다.
if (firstItem.hasAttribute('class')) { // 요소가 class 특성을 가지고 있는지 검사
var attr = firstItem.getAttribute('class'); // 특성 값을 가져 온다.
// 목록 아래에 특성값을 출력한다.
var el = document.getElementById('scriptResults');
el.innerHTML = '<p>The first item has a class name: ' + attr + '</p>';
}
// getElementId() 메서드는 id 특성 값이 one인 요소를 리턴한다.
// 그다음에는 리턴된 요소의 hasAttribute() 메서드를 호출하여 해당 요소에 class 특성이 존재하는지 확인한다.
//getAttribute() 메서드를 이용하여 class 특성 값을 가져온 후에는 이 값을 페이지에 다시 출력한다.
특성을 생성하고 그 값을 변경하기
var firstItem = document.getElementById('one'); // 목록의 첫 번째 아이템을 가져온다.
firstItem.className = 'complete'; // class의 특성값을 변경한다.
var fourthItem = document.getElementsByTagName('li').item(3);// 네 번째 아이템을 가져온다.
fourthItem.setAttribute('class', 'cool'); // 특성을 추가한다.
// className 속성은 class 특성 값을 변경할 때 사용한다. 이때 해당 특성이 존재하지 않으면 지정된 값을 가진 특성을 생성한다.
//setAttribute() 메서드를 이용하면 어떤 속성이든 원하는 것의 값을 변경할 수 있다. 이 메서드는 특성의 이름과 지정될 값 등 두 개의 매개변수를 사용한다.
//요소에 className이나 id 같은 속성이 존재하면 메서드를 통해 특성을 조작하는 것보다 해당 속성을 이용하여 값을 변경하는 것이 더 낫다.
특성제거하기
var firstItem = document.getElementById('one');
if (firstItem.hasAttribute('class')) { // class특성이 존재하는지 확인한다.
firstItem.removeAttribute('class'); // class특성을 제거한다.
}
1.정리) 목록의 시작과 끝에 아이템을 추가한다.
var list = document.getElementsByTagName('ul')[0];
// <ul> 요소를 가져온다.
var newItemLast = document.createElement('li');
// 요소를 생성한다.
var newTextLast = document.createTextNode('cream');
// 텍스트 노드를 생성한다.
newItemLast.appendChild(newTextLast);
// 요소에 텍스트 노드를 생성한다.
list.appendChild(newItemLast);
// 목록의 끝에 요소를 추가한다.
//목록의 시작에 아이템을 추가한다.
var newItemFirst = document.createElement('li');
var newTextFirst = document.createTextNode('kale');
newItemFirst.appendChild(newTextFirst);
list.insertBefore(newItemFirst, list.firstChild);
<단계>
요소 노드를 생성한다.
텍스트 노드를 생성한다.
요소에 텍스트 노드를 추가한다.
DOM 트리에 요소를 추가한다.
네 번째 단계를 위해서는 새로운 노드를 포함하게 될 부모 노드를 먼저 지정해야 한다.
두 경우 모두 부모 요소는 <ul> 요소이다. 이 요소에 대한 참조는 예제 내에서 여러번 참조되기 때문에 변수 list에 저장되어 있다.
2.정리) 모든 아이템에 class 특성을 추가한다.
var listItems = document.querySelectorAll('li');
// 모든 <li> 요소를 찾는다.
// 모든 아이템에 cool 이라는 값을 갖는 class 특성을 추가한다.
var i;
// 카운터 변수
for (i = 0; i < listItems.length; i++) {
// 루프를 실행한다.
listItems[i].className = 'cool';
// class의 특성값을 cool로 변경한다.
}
// 제목에 아이템의 개수를 추천한다.
var heading = document.querySelector('h2');
// h2 요소를 찾는다.
var headingText = heading.firstChild.nodeValue;
// h2 요소의 텍스트를 가져온다.
var totalItems = listItems.length;
// <li> 요소의 개수를 저장한다.
var newHeading = headingText + '<span>' + totalItems + '</span>';
// 제목 내용을 수정한다.
heading.innerHTML = newHeading;
// 새로운 내용이 마크업을 가지고 있으므로 textContent 속성 대신
// innerHTML 속성을 이용하여 h2 요소의 콘텐츠를 수정한다.
//이 예제는 어떤 요소가 가지고 있는 기존 콘텐츠에 새로운 내용을 덧붙이는 방법을 보여준다. 또한, 특성에 기존 값을 덮어쓰지 않고 새로운 값을 추가할 때도 이와 유사한 기법을 사용할 수 있다.
<요약>
- 브라우저는 DOM 트리를 이용하여 페이지를 표현한다.
- DOM 트리는 문서, 요소, 특성, 텍스트 등 네 가지 형식의 노드를 가지고 있다.
- id, class 특성, 태그 이름 또는 css 선택자 문법을 통해 요소 노드를 선택할 수 있다.
- DOM 트리가 하나 이상의 요소를 리턴할 수 있을 때는 항상 NodeList 객체를 리턴한다.
- 요소 노드의 textContent/innerHTML 속성을 이용하거나 DOM 조작 방식을 이용하여 콘텐츠에 접근하고 수정할 수 있다.
- 요소 노드는 여러개의 텍스트 노드 및 자식노드들을 포함할 수 있다.
- 이때 자식 노드들은 서로 이웃 하게 된다.
- 낮은 버전의 브라우저에서는 DOM의 구현 방식이 상이할 수 있다.
- 브라우저들은 DOM 트리를 볼 수 있는 도구를 제공한다.
'매일코딩 > 자바스크립트 개념' 카테고리의 다른 글
[자바스크립트 기초] 함수 이벤트 DOM을 이용한 초미니 프로젝트 1 (2) | 2017.02.28 |
---|---|
[자바스크립트 기초 ]이벤트의 종류와 개념 1 (2) | 2017.02.26 |
[자바스크립트 기초]DOM 문서객체모델의 이해1 (4) | 2017.02.24 |
[자바스크립트 기초]함수 메서드 객체 (2) | 2017.02.23 |
[자바스크립트 기초] 자바스크립트의 기본 명령어 (2) | 2017.02.18 |
댓글