document.getElementById('myId'); //returns HTMLElement or null
document.getElementsByTagName('div'); //returns HTMLCollection
document.getElementsByClassName('myClass'); //returns HTMLCollection
document
HTMLCollection
HTML 엘리먼트는 다른 엘리먼트를 포함할 수 있다.(DOM은 트리구조로 모델링됨)
element.getElementsByClassName('myClass');
element.getElementsByTagName('div');
특정 엘리먼트의 자식 엘리먼트를 검색해 검색의 범위를 좁힐 수 있다.
var myContentsEl = document.getElementById('myContents');
myContentsEl.getElementByTagName('A'); // myContentsEl 하위 엘리먼트중에서 검색
element.addEventListener("click", function() {
// Your code's here
}, false);
이벤트 리스너 안에서의 this 는 이벤트가 적용된 엘리먼트(이벤트 리스너가 화살표 함수인 경우는 이벤트 리스너 생성 당시의 this임)
document.createElement(tagName)
var newDiv = document.createElement("div");
var newP = document.createElement("p");
document.createTextNode(text)
var newText = document.createTextNode("텍스트 노드");
var newText2 = document.createTextNode("HELLO WORLD");
element.appendChild(node)
var newDiv = document.createElement("div");
var newP = document.createElement("p");
var newText = document.createTextNode("HELLO ROOKIES");
newP.appendChild(newText);
newDiv.appendChild(newP);
document.body.appendChild(newDiv);
결과)
<body>
<div>
<p>HELLO ROOKIES</p>
</div>
</body>
Console에서 결과 확인)
document.body.childNodes[0].tagName == 'DIV';
document.body.childNodes[0].childNodes[0].tagName == 'P';
document.body.childNodes[0].childNodes[0].childNodes[0].nodeValue == 'HELLO ROOKIES';
element.removeChild(node)
var newDiv = document.createElement("div");
var newP = document.createElement("p");
var newText = document.createTextNode("HELLO ROOKIES");
newP.appendChild(newText);
newDiv.appendChild(newP);
document.body.appendChild(newDiv); // Body에 추가했지만,
document.body.removeChild(newDiv); // 바로 삭제됨.
element.innerHTML = '<div>text</div>';
HTML 텍스트를 이용해 자식 노드를 생성
document.body.innerHTML = '<div><p>HELLO ROOKIES</p></div>';
결과)
<body>
<div>
<p>HELLO ROOKIES</p>
</div>
</body>
장점)
단점)
주의할점)
innerHTML값이 세팅 될때마다 해당 노드의 모든 자식 엘리먼트를 지우고 다시 만들기 때문에 Addition assginment(+=) 연산자를 직접 사용하는것을 피해야 한다.
// Bad (X)
div.innerHTML = '<p>text1</p>';
// 자식으로 <p>text1</p> 을 만든다.
div.innerHTML += '<p>text2</p>';
// innerHTML === '<p>text1</p><p>text2</p>'
// 지금까지의 DOM Tree를 지우고 <p>text1</p> 부터 다시 만들고 <p>text2</p>도 만든다.
// Good (O)
var content = '';
// HTML 스트링을 미리 만든다.
content += '<p>text1</p>'; // for문 같은 반복문에서 사용된다고 가정할 수 있음.
content += '<p>text2</p>';
div.innerHTML = content; // innerHTML 할당은 한 번만 일어남.
innerHTML과 비슷하지만 텍스트 노드를 생성하거나 참조할 수 있다. 모든 자식 엘리먼트의 텍스트 노드를 확인할 수 있다.
element.textContent = 'new text content';
console.log(element.textContent);
<body>
<ul>
<li><input type="checkbox" /> TODO</li>
</ul>
</body>
이벤트는 특정한 방향으로 전파된다
위에서 아래로
위에서 아래로 => Capturing
body -> ul -> li -> input
아래에서 위로
아래에서 위로 => Bubbling
input -> li -> ul -> body
순서: 캡처링 -> 실제 대상 엘리먼트 -> 버블링
addEventListener()의 세번째 인자로 캡처링/버블링 이벤트를 선택할 수 있다.=> true 면 캡처링 활성화
이벤트 리스너에 첫번째 인자로 넘어오는 Event 객체로 전파를 차단할 수 있다.
var useCapturing = true;
element.addEventListener('click', function(eventObject) {
eventObject.stopPropagation(); // 캡처링이나 버블링을 취소한다.(이벤트 전파를 차단한다)
// etc
eventObject.preventDefault(); // 디폴트 동작을 취소한다.(ex. 링크 이동 차단)
// 체크 박스의 클릭을 취소하는경우 브라우저마다 다른 동작을 한다.
}, useCapturing);
기본적으로 useCapturing 자리가 false 이므로 버블링임(아래->위)
여기서 잠깐!🖐
stopPropagation이 필요한 이유!
이벤트 전파 (버블링) 되어서 다른 이벤트에 영향을 주게 됨
ex) 자식요소가 부모요소 이벤트에 영향을 주게 됨
Event 객체에는 흐름 제어 외에도 많은 유용한 정보를 포함하고 있다. 그 내용은 이벤트 타입에 따라 조금씩 다르다.
<style>
.myClass {
border: 1px solid #f00;
}
#myId {
padding: 5px;
}
</style>
// HTML의 class속성과 동일
element.className = 'myClass';
// 다중 적용시 띄어쓰기
element.className = 'myClass1 myClass2';
// 아이디도 동일하게 적용가능(다중 적용 X)
element.id = 'myId';
document.querySelector('.myClass'); // 처음 찾은 한개만 반환 함.
document.querySelectorAll('.myClass'); // 해당되는 모든 엘리먼트를 찾아서 반환. (Nodelist 타입 - Live Collection이 아님)
element.querySelector(), document.querySelector() 모두 사용가능
// 부모
element.parentNode // 부모 노드
// 형제
element.nextSibling // 다음 형제 노드
element.previousSibling // 이전 형제 노드
// 자식
element.firstChild // 첫번째 자식 노드
element.lastChild // 마지막 자식 노드
element.childNodes // 자식 노드 모두 담고 있는 HTMLCollection