24.02.06
DOM (Document Object Model)
HTML 문서의 내용을 트리형태로 구조화하여 웹페이지와 프로그래밍 언어를 연결시켜 주는 역할
각각의 요소와 속성, 콘텐츠를 표현하는 단위를 노드 (Node)라고 함
+ API (Application Programming Interface) : 설명서
DOM 트리에 접근
document 객체를 통해 HTML 문서에 접근이 가능
(document : 브라우저가 불러온 웹페이지)
= DOM 트리의 진입점 역할을 수행
// 해당하는 Id를 가진 요소에 접근
document.getElementById();
// 해당하는 모든 요소에 접근
document.getElementsByTagName();
// 해당하는 클래스를 가진 모든 요소에 접근
document.getElementsByClassName();
// css 선택자로 단일 요소에 접근
document.querySelector("selector");
// css 선택자로 여러 요소에 접근
document.querySelectorAll("selector");
+ HTMLCollection과 NodeList
getElementsBy 메서드와 querySelectorAll 메서드
= 모두 조건에 일치하는 모든 요소를 찾는다는 공통적인 기능을 수행
하지만 결과물을 콘솔창에서 확인하면 다름
<article id="container">
<ul>
<li>탕수육</li>
<li class="item-second">유산슬</li>
<li>짜장면</li>
</ul>
</article>
<script>
const cont = document.getElementById('container');
const item1 = cont.getElementsByTagName('li');
const item3 = cont.querySelectorAll('li');
</script>
+ item1과 item3을 콘솔에 찍은 결과
item1 : HTMLCollection(3) [li, li.item-second, li]
item3 : NodeList(3) [li, li.item-second, li]
HTMLCollection과 NodeList는 모두 배열과 비슷한 객체 (array-like object) 형태
공통점
안에 있는 데이터에 접근하기 위해서 배열처럼 원소의 인덱스로 접근
차이점
1. 해당 객체에 포함될 수 있는 DOM 요소의 유형
HTMLCollection은 HTML만 포함하지만 NodeList는 모든 유형의 DOM 요소 즉, text, 주석 등을 모두 포함
2. 객체를 구성하는 값이 변경 가능한지 여부
HTMLCollection은 실시간으로 업데이트되며 해당 객체의 각 속성에 대한 변경 사항이 즉시 반영
NodeList는 정적이므로 해당 객체에 대한 변경 사항은 즉시 반영되지 않음
3. 사용할 수 있는 메서드
NodeList는 forEach 같은 배열 메서드를 사용할 수 있지만 HTMLCollection은 또 다른 기능을 지원
DOM 제어 명령어
1. 이벤트 삽입
= target.addEventListener(type, listener)의 문법 형태
<button>HELLO!</button>
// 이벤트의 타입에는 click, mouseover, mouseout, wheel 등 다양한 이벤트를 감지
// listener 함수의 인수에는 이벤트에 대한 정보가 있음
const myBtn = document.querySelector("button");
myBtn.addEventListener('click', function(){
console.log("hello world");
})
2. 클래스 제어
= classList 객체를 통해 요소의 class 속성 제어
<button>Make me BLUE!</button>
const myBtn = document.querySelector("button");
myBtn.addEventListener('click', function(){
// blue라는 클래스의 속성 값을 지정
myBtn.classList.add("blue");
// myBtn.classList.remove("blue"); 클래스를 제거
// myBtn.classList.toggle("blue"); 클래스를 토글함 없으면 넣어주고 있으면 제거
// myBtn.classList.contains("blue"); 해당하는 클래스가 있는지 확인
})
3. 요소 제어
= DOM api를 이용하면 요소를 새롭게 생성하고 위치시키며 제거할 수 있음
ㄱ. document.createElement(target) : target 요소를 생성
ㄴ. document.createTextNode(target) : target 텍스트를 생성
ㄷ. element.appendChild(target) : target 요소를 element의 자식으로 위치
ㄹ. element.removeChild(target) : element의 target 자식 요소를 제거
<ul></ul>
<button>Make me MORE!</button>
const myBtn = document.querySelector("button");
const myUl = document.querySelector("ul");
myBtn.addEventListener('click', function(){
for(let i=0; i < 5; i++){
const myLi = document.createElement('li');
myUl.appendChild(myLi);
}
})
ㅁ. element.append(target) : target 요소를 element의 자식으로 위치
appendChild와 다른 점은 노드뿐만 아니라 여러 개의 노드를 한 번에 그리고 텍스트도 자식 노드로 포함시킬 수 있음
ㅂ. target.remove() : target 요소를 제거
const myBtn = document.querySelector("button");
const myUl = document.querySelector("ul");
myBtn.addEventListener('click', function(){
for(let i=0; i < 5; i++){
const myLi = document.createElement('li');
const btnDel = document.createElement('button');
const btnTxt = document.createTextNode('버튼');
btnDel.append(btnTxt);
btnDel.addEventListener('click', ()=>{
myLi.remove();
});
myLi.append('삭제하기: ', btnDel);
myUl.appendChild(myLi);
}
});
<div id="parentElement">
<span id="childElement">hello guys~</span>
</div>
// parentElement.insertBefore(target, location); target요소를 parentElement의 자식인 location 위치 앞으로 이동
var span = document.createElement("span");
var sibling = document.getElementById("childElement");
var parentDiv = document.getElementById("parentElement");
parentDiv.insertBefore(span, sibling);
4. JavaScript 문자열을 사용해 element, text 노드를 생성하거나 추가
= DOM api를 이용하면 요소 안의 값에 접근하여 값을 가져오거나 변경할 수 있음
<p></p>
<input type="text">
<button>Write Something!</button>
const myBtn = document.querySelector("button");
const myP = document.querySelector("p");
const myInput = document.querySelector("input");
// ex) 1 : input 창에 글자를 써넣고 버튼을 누르면 글자를 p 태그에 삽입하는 코드
myBtn.addEventListener('click', function(){
myP.textContent = myInput.value;
});
// ex) 2 : input 창에 글자를 쓰면 실시간으로 p 태그에 반영되는 코드
// input 요소에 'input' 이벤트를 연결하면 실시간으로 값이 반영되게 만들 수도 있음
myInput.addEventListener('input', ()=>{
myP.textContent = myInput.value;
});
myP.innerHTML = "<strong>I'm Strong!!</strong>";
// innerHTML : 요소(element) 내에 포함된 HTML 마크업을 가져오거나 설정
// 중요한 기능은 innerHTML로 값을 할당할 때 마크업으로 변환할 수 있는 문자열이 있다면 마크업으로 만들어 보여준다는 것
// 만약 그런 문자열이 없다면 그냥 문자열만 콘텐츠로 설정
// innerText 속성 : 요소의 렌더링 된 텍스트 콘텐츠
// (렌더링된에 주목, innerText는 텍스트 내에 문법적으로 처리가 가능한 텍스트가 있으면 처리가 끝난 결과물을 텍스트로 전달)
// textContent 속성은 노드의 텍스트 콘텐츠를 표현, 콘텐츠를 단순히 텍스트로만 다룸
참고 : (innerHTML 사용 시 주의 사항) https://developer.mozilla.org/ko/docs/Web/API/Element/innerHTML#security_considerations
참고 : (innerText와 textContent의 차이) https://developer.mozilla.org/ko/docs/Web/API/HTMLElement/innerText#예제
5. 속성 제어
= 자바스크립트를 사용하여 요소의 속성을 제어하는 방법
ㄱ. 요소의 스타일을 제어하는 style 객체
= 요소는 그 안에 CSSStyleDeclaration 객체라 불리는 style 객체가 존재
요소의 스타일 정보를 가지고 있으며 스타일과 관련한 프로퍼티와 메서드를 지원함
const target = document.querySelector("p");
const txtColor = target.style.color; // 현재 스타일 정보를 가져옴
target.style.color = "red"; // 현재 스타일 정보를 변경
target.style.fontWeight = "bold"; // 현재 스타일 정보에 font-weight 속성이 없다면 추가
target.style.color = null; // 현재 스타일 정보를 제거 (초기화)
+ style 객체의 속성 식별자 규칙
1. 속성 이름이 한 글자라면 그대로 사용 (height, color ...)
2. 속성 이름이 대시(-)를 통해 여러 단어로 나눠져 있는 경우는 카멜케이스로 사용 (background-image를 backgroundImage로 사용)
3. float 속성의 경우 이미 자바스크립트의 예약어로 존재하기 때문에 cssFloat로 사용
ㄴ. 속성에 접근하고 수정할 수 있는 Attribute 메서드
= getAttribute 메서드는 요소의 특정 속성 값에 접근할 수 있도록 함
= setAttribute 메서드는 요소의 특정 속성 값에 접근하여 값을 수정 <p id='myTxt'>hello lions</p>
<img src='https://static.ebs.co.kr/images/public/lectures/2014/06/19/10/bhpImg/44deb98d-1c50-4073-9bd7-2c2c28d65f9e.jpg'>
<script>
const target = document.querySelector('p');
const myimg = document.querySelector('img');
const idAttr = target.getAttribute('id');
console.log(idAttr);
myimg.setAttribute("src", "https://img.wendybook.com/image_detail/img159/159599_01.jpg");
</script>
ㄷ. 요소에 데이터를 저장하도록 도와주는 data 속성
= data 속성을 사용하면 HTML 요소에 추가적인 정보를 저장하여 마치 프로그램 가능한 객체처럼 사용 가능
(data 속성의 이름에는 콜론(:)이나 영문 대문자가 들어가면 안 됨)
<img
class="terran battle-cruiser"
src="battle-cruiser.png"
data-ship-id="324"
data-weapons="laser"
data-health="400"
data-mana="250"
data-skill="yamato-cannon"
/>
<script>
const img = document.querySelector('img')
console.log(img.dataset);
console.log(img.dataset.shipId);
</script>
6. 더 인접한 곳 (Adjacent)으로 정밀하게 배치
= insertAdjacentHTML : 요소 노드를 대상의 인접한 주변에 배치
<strong class="sayHi">
반갑습니다.
</strong>
const sayHi = document.querySelector('.sayHi');
sayHi.insertAdjacentHTML('beforebegin', '<span>안녕하세요 저는</span>');
sayHi.insertAdjacentHTML('afterbegin', '<span>수현입니다</span>');
sayHi.insertAdjacentHTML('beforeend', '<span>댓글을 남겨주시면</span>');
sayHi.insertAdjacentHTML('afterend', '<span>답글을 적어드릴게요</span>');
= begin 여는 태그, end 닫는 태그를 의미
7. DOM 안에서 노드 탐색
<article class="cont">
<h1>안녕하세요 저는 이런 사람입니다.</h1>
<p>지금부터 자기소개 올리겠습니다</p>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Deserunt incidunt voluptates laudantium fugit, omnis
dolore itaque esse exercitationem quam culpa praesentium, quisquam repudiandae aut. Molestias qui quas ea iure
officiis.
<strong>감사합니다!</strong>
</article>
const cont = document.querySelector(".cont");
console.log(cont.firstElementChild); // 첫 번째 자식을 찾음
console.log(cont.lastElementChild); // 마지막 자식을 찾음
console.log(cont.nextElementSibling); // 다음 형제요소를 찾음
console.log(cont.previousSibling); // 이전 형제노드를 찾음
console.log(cont.children); // 모든 자식요소를 찾음
console.log(cont.childNodes); // 모든 자식노드를 찾음
console.log(cont.parentElement); // 부모 요소를 찾음
// 자기 자신부터 시작해 부모로 타고 올라가며 가장 가까운 cont 클래스 요소를 찾음
// 단, 형제요소는 찾지 않음
console.log(cont.querySelector('strong').closest('.cont').innerHTML);
이벤트 객체
= 이벤트에서 호출되는 핸들러에는 이벤트와 관련된 모든 정보를 가지고 있는 매개변수가 전송
<article class="parent">
<ol>
<li><button class="btn-first" type="button">버튼 1</button></li>
<li><button type="button">버튼 2</button></li>
<li><button type="button">버튼 3</button></li>
</ol>
</article>
const btnFirst = document.querySelector('.btn-first');
btnFirst.addEventListener('click', (event) => {
console.log(event);
});
7일 글에 이어서 DOM의 이벤트 흐름부터 알아보겠습니다.
이번주는 스스로 컨디션이 많이 좋지 못해 미루었던 일들이 많은데 역시 사람은 할 일은 그때그때 다 해야겠어요.
미루다가 하려니 나 자신이 너무 힘들고 저랑은 안 맞는 스타일 같군요 x_X
정리한 파일은 GitHub에서 확인하실 수 있습니다.
이 글을 보시는 분은 즐거운 설 연휴 보내세요! 6일 정리글이 9일에 올라가는 마법..
https://github.com/soohyun020812/ormcamp
GitHub - soohyun020812/ormcamp: 오름캠프 교육에서 활용한 실습 내용들 정리
오름캠프 교육에서 활용한 실습 내용들 정리. Contribute to soohyun020812/ormcamp development by creating an account on GitHub.
github.com