[공부 내용 정리]
DOM (Document Object Model)
- 브라우저에서 제공하는 API
- API : Application Programming Interface. 한마디로 '설명서'
DOM API란?
- HTML 문서의 내용을 트리형태로 구조화하여 웹페이지와 프로그래밍 언어를 연결시켜주는 역할을 함.
- 이때 각각의 요소와 속성, 콘텐츠를 표현하는 단위를 노드(node) 라고 함.
- 결국 DOM은 수많은 노드들의 집합임.
DOM 트리에 접근
- document 객체를 통해 HTML 문서에 접근함.
- document는 브라우저가 불러온 웹페이지를 나타내며, DOM 트리의 진입점 역할.
// 해당하는 Id를 가진 요소에 접근하기
document.getElementById();
// 해당하는 모든 요소에 접근하기
document.getElementsByTagName();
// 해당하는 클래스를 가진 모든 요소에 접근하기
document.getElementsByClassName();
// css 선택자로 **단일 요소**에 접근하기
document.querySelector("selector"); //
// css 선택자로 **여러 요소**에 접근하기
document.querySelectorAll("selector");
- 특정한 쿼리(CSS 선택자)를 날려서 접근할 수도 있음(querySelector) -> 가장 많이 사용함!
- querySelector가 같은 클래스를 갖는 요소를 선택할 경우, 첫 번째(단일요소)만 선택.
DOM 제어 명령어
1. 이벤트 삽입
target.addEvenListener(type, listener) 의 문법 형태를 지님.
<button>HELLO!</button>
* JavaScript 제어 명령어는 script 태그 안에 넣어서 실행시켜야함! (따로 파일 분리를 할수도 있음.)
// 이벤트의 타입에는 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>
myBtn.addEventListener('click', function(){
// blue라는 클래스 속성 값 지정 가능
myBtn.classList.remove("blue"); // 클래스 제거
myBtn.classList.toggle("blue"); // 클래스 토글(껐다켰다)
myBtn.classList.contains("blue"); // 해당하는 클래스가 있는지 확인
3. 요소 제어
DOM api를 이용해서 요소를 새롭게 생성하고, 위치하고, 제거할 수 있음.
4. JavaScript 문자열을 사용해 element, text 노드를 생성하거나 추가하기
DOM api를 이용해서 요소 안의 값에 접근하여 값을 가져오거나, 변경할 수 있음.
<script>
// 코드를 <body> 태그의 끝에 위치시킴
const myBtn = document.querySelector("button");
const myP = document.querySelector("strong");
const myInput = document.querySelector("input");
myBtn.addEventListener('click', function() {
myP.innerHTML = myInput.value;
});
// input 요소에 'input' 이벤트를 연결하면 실시간으로 값이 반영되게 만들 수도 있음!
myInput.addEventListener('input', () => {
myP.textContent = myInput.value;
});
</script>
* 둘 다 버튼을 눌렀을 때 div 영역에 내용을 출력하는데 사용하는 프로퍼티
- innerHTML : 태그를 문자열에 입력하면 태그로 인식해서 태그에 맞게 출력됨.
- innerText : 태그를 입력해주어도 문자열 그대로 받아들여서 문자열 그대로 출력됨.
- textContent : 노드의 텍스트 콘텐츠를 표현. 콘텐츠를 단순히 텍스트로만 다룸.
5. 속성 제어하기
-> 요소의 style을 제어하는 객체
-> 속성에 접근하고 수정할 수 있는 Attribute 메서드
-> 요소에 데이터를 저장하도록 도와주는 data 속성
6. 더 인접한곳(Adjacent)으로 정밀하게 배치하기
insertAdjacentHTML : 요소 노드를 대상의 인접한 주변에 배치함.
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>');
7. DOM 안에서 노드 탐색하기
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);
이벤트 객체
이벤트에서 호출되는 핸들러에는 이벤트와 관련된 모든 정보를 가지고 있는 매개변수가 전송됨. 이것이 바로 이벤트 객체!
const btnFirst = document.querySelector('.btn-first');
btnFirst.addEventListener('click', (event) => {
console.log(event);
});
-> 첫 번째 버튼에만 핸들러를 넣어줌.
이벤트 흐름
브라우저 화면에서 이벤트가 발생하면, 브라우저는 가장 먼저 이벤트 대상을 찾기 시작함.
버블링 단계 : 한 요소에 이벤트가 발생하면 이 요소에 할당된 핸들러가 동작하고, 이어서 부모 요소의 핸들러가 동작하고, 최상단의 부모 요소를 만날 때까지 반복되면서 핸들러가 동작현상. 아래서부터 위로 올라가는 것
캡쳐링 단계 : 버블링과는 반대로 최상위 태그에서 해당 태그를 찾아 내려가는 것. 위에서부터 아래로 내려가는 것
이벤트 전파 : 이러한 과정에서 이벤트 리스너가 차례로 실행되는 것.
이벤트 target, currentTarget
- target : 실제 이벤트가 발생하는 요소. 이 속성을 통해 이벤트 리스너가 없는 요소의 이벤트가 발생했을 때도 해당 요소에 접근 할 수 있음.
- currentTarget : 이벤트 리스너가 달린 요소
이벤트 위임
우리는 이벤트의 흐름을 통해 이벤트 리스너가 없는 요소의 이벤트가 발생했을 때도 해당 요소에 접근 할 수 있다는 것을 알게됨. 이것을 이용해 마치 리스너가 있는 것 처럼 사용할 수 있음. 이러한 테크닉을 이벤트 위임이라고 함.
이벤트의 this
이벤트 리스너 함수 내부에서의 this 값은 이벤트가 연결된 노드를 참조함.
preventDefault()
브라우저의 기본 이벤트 동작을 취소함.
-> 브라우저의 기본 동작을 중지하고 자바스크립트를 통해 기능을 처리하고자 할 때 사용함.
<body>
<!-- 앵커의 기본 동작을 중지 -->
<a href="https://www.naver.com" class="link">네이버 링크입니다만..</a>
<script>
const link = document.querySelector('.link');
link.addEventListener('click', (event) => {
console.log('clicked');
event.preventDefault();
})
</script>
<!-- submit 의 기본 동작을 중지 -->
<form action="">
<button type="submit" class="submit">제출</button>
</form>
<script>
const submit = document.querySelector('.submit');
submit.addEventListener('click', (event) => {
console.log('clicked');
event.preventDefault();
})
</script>
</body>
stopPropagation()
앞서 공부한 preventDefault를 통해 브라우저의 기본 이벤트 동작을 취소할 수 있지만, 이벤트 흐름을 막지는 못함.
따라서 만약 이벤트 흐름을 막고 싶다면 event.stopPropagation() 코드를 추가하면 됨.
실습)
<body>
<!-- submit 의 기본 동작을 중지 -->
<h1>나의 todo list</h1>
<p>1. 오늘 저녁에는 부대찌개를 끓여 먹겠다.<button type="button">삭제</button></p>
<p>2. 후식으로 슈팅스타를 먹겠다.<button type="button">삭제</button></p>
<p>3. 자기 전에 반드시 내일 아침 메뉴를 생각해두겠다.<button type="button">삭제</button></p>
<script>
// 각 <p> 태그에 대해 반복문 실행
const txts = document.querySelectorAll('p');
txts.forEach((item)=>{
// 클릭 이벤트 리스너 추가
item.addEventListener('click', (event)=>{
// 그 텍스트 내용을 알림창으로 표시함.
alert(event.target.childNodes[0].data);
});
});
// 각 <button> 태그에 대해 반복문 실행
const btns = document.querySelectorAll('button');
btns.forEach((item)=>{
// 클릭 이벤트 리스너 추가
item.addEventListener('click', (event)=>{
// 확인 대화 상자를 통해 삭제 여부 물어봄.
const reselt = confirm('삭제하시겠습니까?');
// 이벤트 전파를 중지 (부모 요소의 클릭 이벤트 등을 방지함.)
event.stopPropagation();
// 확인을 선택하면 해당 <P> 요소를 삭제함.
if(reselt){
event.target.parentElement.remove();
}
});
})
</script>
</body>
처음 배우는 DOM 개념은 너무 어려웠다.. 이해 안되는 건 구글링하고 유튜브 찾아보며 겨우 이해했지만 앞으로 다양한 코드를 직접 써보고 고생하며 알아가야 진정 익숙해질 것 같다. 갈길이 머니까 더 열심히 하자!!
'Front-End > JS' 카테고리의 다른 글
[JS] 객체지향 프로그래밍 (0) | 2024.01.15 |
---|---|
[JS] This (0) | 2024.01.12 |
[JS] Type(배열, 객체) (0) | 2024.01.12 |
[JS] for문/while문 (1) | 2024.01.11 |
[JS] 변수/함수/조건문 (0) | 2024.01.10 |