[코드스쿼드] DOM node 생성 및 추가
웹자판기 - DOM & Event 2번째 강의 DOM node 생성 및 추가를 정리한 글 입니다.
목표
- 다양한 DOM(Document Object Model) APIs를 이해한다
- element와 text node를 생성해서 화면에 추가할 수 있다
node 탐색 방법
node
- textNode (텍스트도 하나의 node 이다)
- elementNode
대부분 querySelector 로 div 를 찾고나서
.firstChild
를 수행하면#text
가 출력되는데 이것은 공백을 뜻함 (각 태그 사이의 공백들)- 그래서
.firstElementChild
로 해결할 수 있다 .nextSibling
이면 공백(#text)이 출력됨.nextElementSibling
으로 해결
querySelector 로 찾고
.childNodes
를 해주면배열형태
로 출력됨자손 노드 (자식의 자식노드) 까지는 찾을 수 없음
- 브라우저 지원범위를 항상 확인해볼 것 (현 크롬 버전은 67, 베타 69)
nodeType의 이해
DOM node는 여러가지 Type이 있다. 어떤 타입이 있는지 이해한다.
var body = document.querySelector("div");
body.nodeType;
/* OUTPUT : 1 (ELEMENT_NODE)*/
var div = document.querySelector("body > div");
body.nodeType;
/* OUTPUT : 1 (ELEMENT_NODE)*/
body.firstChild.nodeType;
/* OUTPUT : 3 (TEXT_NODE)*/
해당 body.firstChild
는 공백(#text) 이 출력되기 때문에 nodeType 이 3 으로 나온것임
nodeType
을 이용해서 DOM을 찾아갈 때, Element 인지 Text 인지 알아낼 수 있다
node 생성과 추가
노드를 새롭게 만들고 DOM 트리에 추가하는 방법을 설명하고, 실무에서 많이 사용하는 방법이므로 꼭 실습해본다.
- 트리구조를 타고 올라간다던가
- 어떤 노드를 삭제한다던가
- 특정 노드 전 후로 새로운 노드를 추가한다던가
DOM 탐색 APIs
tagName : 엘리먼트의 타입이름을 얻을 수 있다.
XHTML(또는 XML) 타입에서는 소문자로 출력되며,
HTML
에서는 무조건 대문자로 출력된다.<span id="born">When I was born...</span>
var span = document.getElementById("born"); console.log(span.tagName); // "SPAN"
textContent : 노드와 그 자손의 텍스트 내용을 표시하고, 설정도 가능하다.
// <span id="born">HE<span>L</span>LO</span> console.log(span.textContent); // "HELLO" console.log(span.innerHTML); // "HE<span>L</span>LO" console.log(span.innerText); // "HELLO"
- innerText 와의 차이점
- textContent 는
- innerText 는 style 을 인지하고 숨겨진 요소들의 텍스트를 반환하진 않지만 textContent 는 반환함
- innerText 는 CSS 스타일링을 인지하기 때문에 레이아웃의 변화를 가져올 수 있지만, textContent는 그렇지 않음
- innerText 는 요소의 자식노드를 지우는 것 뿐만아니라, 텍스트 노드의 모든 자손을 영구적으로 제거함
- innerHTML 과의 차이점
- innerHTML 은 HTML을 반환함
- textContent가 텍스트를 HTML로 파싱하지 않기 때문에 종종 더 좋은 성능을 보여줌
- textContent는 XSS 를 방지할 수 있음
- innerText 와의 차이점
nodeType :
elements
text
comments
처럼 서로 다른 종류의 노드를 구별하는데 사용할 수 있음childNodes : 주어진 요소의 자식 노드 모음 (collection)을 반환함 (NodeList)
// parg는 <p> 요소 개체 참조 if (parg.hasChildNodes()) // 그래서, 먼저 개체가 찼는 지(자식 노드가 있는 지) 검사 { var children = parg.childNodes; for (var i = 0; i < children.length; i++) { // children[i]로 각 자식에 무언가를 함 // 주의: 목록은 유효해(live), 자식 추가나 제거는 목록을 바꿈 }; };
firstChild : 트리에서 노드의 첫 번째 자식이나 null(노드가 자식이 없으면)을 반환함
<p id="para-01"> <span>First span</span> </p> <script type="text/javascript"> var p01 = document.getElementById('para-01'); alert(p01.firstChild.nodeName) </script>
<ul id="foo"> <li>First (1)</li> <li>Second (2)</li> <li>Third (3)</li> </ul>
var foo = document.getElementById('foo'); console.log(foo.firstElementChild.textContent); // "First (1)"
parentElement : 현재 노드에서 부모 노드를 가리킨다.
if (node.parentElement) { node.parentElement.style.color = "red"; }
부모의
childNodes
목록에서 지정된 노드 바로 다음에 있는 노드를 반환하거나 지정된 노드가 해당 목록의 마지막 노드이면null
을 반환 (#text 데이터를 가져온다는 것을 중점으로 볼 것)<div id="div-01">Here is div-01</div> <div id="div-02">Here is div-02</div> <script type="text/javascript"> var el = document.getElementById('div-01').nextSibling, i = 1; console.log('Siblings of div-01:'); while (el) { console.log(i + '. ' + el.nodeName); el = el.nextSibling; i++; } </script> /************************************************** 로드될 때 다음과 같이 콘솔에 기록됩니다. : Siblings of div-01 1. #text 2. DIV 3. #text 4. SCRIPT **************************************************/
<div id="div-01">Here is div-01</div> <div id="div-02">Here is div-02</div> <script type="text/javascript"> var el = document.getElementById('div-01').nextElementSibling; console.log('Siblings of div-01:'); while (el) { console.log(el.nodeName); el = el.nextElementSibling; } </script> /************************************************** 로드될 때 다음과 같이 콘솔에 기록됩니다. : Siblings of div-01: DIV SCRIPT **************************************************/
DOM 조작 APIs
삭제, 추가, 이동, 교체를 위해 사용하는 DOM API 이다.
추가
- HTML 문서에 태그들을 추가하는 작업이 쉬운일은 아님
객체화
해서 추가한다- 객체화란 ? DOM API 를 이용해서 정해진 메서드들을 통해서 DOM Tree에 맞는 속성값으로 넣는 것
- 개발자 도구에서 선택한 것은 간단하게
$0
으로 접근할 수 있음
/* 표준 방법 */ var div = document.createElement("div"); var str = document.createTextNode("오늘 하루는 정말 ..좋아"); div.appendChild(str); $0.appendChild("div"); /* 여기서 선택한 태그의 마지막 자식으로 추가됨*/
removeChild() : 자식의 엘리먼트를 삭제하는 문법
// Get the <ul> element with id="myList" var list = document.getElementById("myList"); list.removeChild(list.childNodes[0]); // Remove <ul>'s first child node (index 0)
appendChild() : 한 노드를 특정 부모 노드의 자식 노드 리스트 중 마지막 자식으로 붙임
// 새로운 단락 요소를 생성하고 문서에 있는 바디 요소의 끝에 붙입니다. var p = document.createElement("p"); document.body.appendChild(p);
<ul id="myList"> <li>Coffee</li> <li>Tea</li> </ul> <p>Click the button to insert an item to the list.</p> <button onclick="myFunction()">Try it</button> <script> function myFunction() { var newItem = document.createElement("LI"); var textnode = document.createTextNode("Water"); newItem.appendChild(textnode); var list = document.getElementById("myList"); list.insertBefore(newItem, list.childNodes[0]); } </script> <!-- Example explained: First create a LI node, then create a Text node, then append the Text node to the LI node. Finally insert the LI node before the first child node in the list. -->
nextSibling 를 통해서 삽입하는 경우도 있음
<div id="parentElement"> <span id="childElement">foo bar</span> </div> <script> // Create a new, plain <span> element var sp1 = document.createElement("span"); // Get a reference to the element, before we want to insert the element var sp2 = document.getElementById("childElement"); // Get a reference to the parent element var parentDiv = sp2.parentNode; // Insert the new element into the DOM before sp2 parentDiv.insertBefore(sp1, sp2); </script>
parentDiv.insertBefore(sp1, sp2.nextSibling);
var dupNode = node.cloneNode(deep);
- node : 복제되어야 할 node
- dupNode : 복제된 새로운 node
- deep
- true : 해당 node의 childern 까지 복사
- false : 해당 node만 복사
replaceNode = parentNode.replaceChild(newChild, oldChild);
- replaceNode 는 교체된 노드로서, oldChild 와 동일한 노드이다.
- newChild 는 oldChild를 교체할 새로운 노드이다. (만약 이미 DOM 안에 존재한다면 가장 먼저 제거됨?)
- oldChild 는 이미 존재하는, 교체될 자식 노드이다.
// <div> // <span id="childSpan">foo bar</span> // </div> // 텅빈 요소 노드를 하나 생성합니다. // ID도, 속성도, 컨텐츠도 없습니다. var sp1 = document.createElement("span"); // 'newSpan'이란 id 속성을 부여합니다. sp1.id = "newSpan"; // 새로운 요소를 위한 컨텐츠를 생성합니다. var sp1_content = document.createTextNode("new replacement span element."); // 컨텐츠를 생성한 요소에 붙입니다. sp1.appendChild(sp1_content); // DOM에 존재하던, 교체되야할 노드를 참조합니다. var sp2 = document.getElementById("childSpan"); var parentDiv = sp2.parentNode; // 이미 존재하던 sp2 노드를 새로운 span 요소인 sp1으로 교체합니다. parentDiv.replaceChild(sp1, sp2); // 결과: // <div> // <span id="newSpan">new replacement span element.</span> // </div>