DOM의 모든 것

전서희·2022년 5월 12일
0

JavaScript

목록 보기
1/3
post-thumbnail

DOM (Document Object Model)

: 문서, 객체, 모델

🍒 1. DOM 이란?

  • HTML 문서 내용을 트리형태로 구조화하여 웹페이지와 프로그래밍 언어를 연결시켜줌
  • 각각의 요소와 속성, 콘텐츠를 표현하는 단위를 노드(node)

DOM 기능

  1. console
  2. window.navigator
    • 사용히는 브라우저에 대한 정보
  3. window.devicePixelRatio
    • 픽셀 ratio 값에 대한 정보!

✏️ 오늘의 용어정리

  • Parse: 어떤 데이터 형태를 다른 데이터로 바꿔주는 것
  • DOM API: 브라우저가 우리에게 제공해주는 인터페이스, DOM API에 접근해서 변수에 넣어주며는 필요할 때마다 쓸 수 있음
  • Window: window 객체는 웹 브라우저의 창(window)을 나타내는 객체, 자바스크립트의 모든 객체, 전역함수, 전역 변수들은 자동으로 window 객체의 프로퍼티가 된다. 브라우저 공간을 통해 문법적인 공간을 작성할 수 있음

🍒 2. DOM 트리에 접근하기

  • Document에 다이빙 하려면 Document 부터 시작해야 함
  • 변수에 담을 수 있음
  • DOM API를 이용해서 node에 접근
//1. 해당하는 Id를 가진 요소에 접근하기
document.getElementById()

//2. 해당하는 모든 요소에 접근하기
//- 배열처럼 생겼지만, 배열은 아님 Arraylike Object인 HTML Collection 반환
document.getElementsByTagName(); 

//3. 해당하는 클래스를 가진 모든 요소에 접근하기
document.getElementsByClassName(); 

 //4. CSS선택자로 단일 요소에 접근하기
//- 해당하는 가장 처음에 나타나는 것을 선택해줌(하나만)
// Html 전체 문서 내에서 찾기 때문에 비용이 많이 든다 -> 변수로 빼놓을 것
document.querySelector("selector");

//4. CSS선택자로 여러 요소에 접근하기
// - 여러가지
document.querySelectorAll("selector"); 
  • 1,2,3은 여러개를 한 번에 잡고, 4,5는 하나씩만 찝어서 잡을 수 있음
  • CSS 선택자를 사용할 수 있어서 더 편하고 우리에게 익숙한 형태이기 때문에 실전에서는 4,5번을 주로 사용함

💡문제) 배운 문법을 바탕으로 첫번째 item-second와 첫번째 li를 콘솔로 출력해보자.

<body>
    점심 식단
    <article id="container">
        <ul>
            <li>탕수육</li>
            <li class="item-second">유산슬</li>
            <li>짜장면</li>
        </ul>
    </article>
    저녁 식단
    <article>
        <ul>
            <li>된장국</li>
            <li class="item-second">김치찌게</li>
            <li>해장국</li>
        </ul>
    </article>
</body>

👆🏻 첫번째

item-second를 출력하기 위해서는 어떤 것을 사용해야할까?
item-second는 클래스이름이기 때문에 getElementsByClassName을 사용해주면 된다!
답:

document.getElementsByClassName('item-second')[0]

0을 해주는 이유는 안해주면 아래 결과처럼 HTML Collection이 나온다. 우리는 첫번째 있는 요소를 가져오고 싶은 것이기 때문에 인덱스 0번째를 가져오라고 [0]를 추가해주면 된다.

🤘🏻두번째

li의 첫번째 요소를 가져오려면 li는 태그이기 때문에 getElementsByTagName('li')를 사용해주면 된다.

답:

document.getElementsByTagName('li')[0]

마찬가지로 6개의 HTMLCollection이 나오기 때문에 인덱싱을 해서 원하는 값만 추출해주면 된다.

🍕 HTML Collection 과 NodeList

HTMLCollectionNodeList
getElementsByTagName, getElementsByClassNamequerySelectorAll
  • 배열처럼 length와 index를 사용할 수 있다.
  • DOM API가 여러개의 결과값을 반환하기 위한 DOM 컬렉션 객체
  • 유사 배열 객체이면서 iterable이기 떄문에 for of로 순회 가능
  • 배열로 변환 후 사용이 권장됨

🍒 3. DOM 제어 명령어

🍕 1. 이벤트 삽입

target.addEventListner(type, listener)
  • 이벤트는 위와 같은 문법 형태를 가진다
  • type에는 click, mouseover, mouseout, wheel등의 이벤트를 넣어주면 된다.
  • listner 은 이벤트에 대한 정보가 담긴 callback 함수를 넣어주면 된다.

❗ 버튼을 클릭하면 hello world가 콘솔창에 출려되는 코드를 작성해보자

<button>HELLO!</button>
const myBtn = document.querySelector("button");

myBtn.addEventListener('click', function(){
	console.log("hello world");
})

+코드펜

[이벤트 참조 MDN 문서 참고]
https://developer.mozilla.org/ko/docs/Web/Events

🍕 2. 클래스 제어

DOM api를 통해 요소의 class 속성을 제어할 수 있다.

내용설명
classList.add()클래스 추가
classList.remove()클래스 삭제
classList.toggle()클래스 있으면 삭제, 없으면 추가

❗ 버튼을 클릭하면 button에 blue 클래스를 추가해주자//여기까지

<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”);   해당하는 클래스가 있는지 확인합니다.
})

자바스크립트로 style을 추가해서 바로 색상 등을 변경할 수 있음
-> 근데 내부에서 바로 바꿔지기 때문에 별로 추천은 안함
클래스 선택자를 주로 쓴다.

documnet.querySelector('.blue').classList.contains('');

contains를 통해 헤당하는 클래스가 있는지 없는지도 확인 가능하다.

문제

querySelector 함수는 비용이 많이 드는 함수
메모리도 많이 먹고, 속도도 느림

🍕 3. 요소 제어

DOM api를 이용하면 요소를 새롭게 생성하고, 위치하고, 제거할 수 있다.
사진 등도 자유롭게 넣을 수 있음

<ul></ul>
<button>Make me MORE!</button>
// document.createElement(target); target 요소를 생성합니다.
// document.createTextNode(target); target 텍스트를 생성합니다.
// element.appendChild(target);    target 요소를 element의 자식으로 위치합니다.(마지막 자식 요소) -> 두번째, 세번쨰 자식 요소에 넣고 싶다면? 아래에 insertBefore 사용!
// element.removeChild(target);    element의 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');
		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");

myBtn.addEventListener('click', function(){
	myP.textContent = myInput.value;
});
// input 요소에 'input' 이벤트를 연결하면 실시간으로 값이 반영되게 만들 수도 있습니다.
myInput.addEventListener('input', ()=>{
  myP.textContent = myInput.value;
});

myP.innerHTML = "<strong>I'm Strong!!</strong>";
myP.outerHTML = "<div></div>";
//outer은 덮어쓰기를 해줍니다.


// innerHTML 은 요소(element) 내에 포함된 HTML 마크업을 가져오거나 설정합니다.
// innerText 속성은 요소의 렌더링된 텍스트 콘텐츠를 나타냅니다. (렌더링된에 주목하세요. innerText는 "사람이 읽을 수 있는" 요소만 처리합니다.) 사람이 읽을 수 있는 !!!
// textContent 속성은 노드의 텍스트 콘텐츠를 표현합니다.

순수하게 글짜만 넣을꺼야 하면은 textContent가 빠르게 넣어진다.
그래도 tag를 포함해서 넣어주려면 innerHTML을 사용하는게 좋아.(html로 바꿔주는 문자열을 넣으려면!)
innerHTML은 보안 이슈가 발생할 수도 있다.
밑에 글 참고

https://developer.mozilla.org/ko/docs/Web/API/Element/innerHTML#security_considerations

  • InnerHTML은 script 태그가 실행되지 않도록 자동으로 막아줌

  • HTML, CSS, JavaScript는 완전히 분리해주세요! - 유지보수에서 좋음

🍕 5. 더 인접한곳(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>');

🍕 6. DOM 안에서 노드 탐색하기

🍒 4. 이벤트 객체

이벤트에서 호출되는 핸들러에는 이벤트와 관련된 모든 정보를 가지고 있는 매개변수가 전송됩니다. 이것이 바로 이벤트 객체입니다!

<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);
});

🍒 5. 이벤트 흐름

브라우저 화면에서 이벤트가 발생하면 브라우저는 가장 먼저 이벤트 대상을 찾기 시작합니다.

브라우저에서 이벤트가 발생하면 브라우저는 이벤트가 어디에서 발생했는지 가장 먼저 찾음!
마우스를 움직이는 것만으로도 이벤트임, 휠을 사용하는 것

브라우저가 이벤트 대상을 찾아갈 때는 가장 상위의 window 객체부터 document, body 순으로 DOM 트리를 따라 내려갑니다. 이를 캡처링 단계라고 합니다.

그 중간에 , 부모 요소에 캡쳐링 이벤트가 있으면 캡쳐링 이벤트 리스너를 실행시킴

addEventListner('이벤트', '함수', true)
세번째 요소가 true 이면 캡쳐링 이벤트가 시작이 돼요
default 값은 없어요

버블링 단계에서 실행하는 이벤트
캡쳐링 이벤트는 캡쳐링 이벤트를 실행시키고
버블링 이벤트는 버블링 이벤트를 실행시킨다.

addEventLisnter의 세번쨰 요소가 false 이거나 명시해주지 않은 것을
버블링이라고 한다.

🍒 6. 이벤트 target, currentTarget

event.target
이벤트가 일어난 곳에 대한 정보가 담겨져 있음
이벤트가 발생한 지점이 타겟에 저장된다.
누른 버튼 그 자체

event.currentTarget
이벤트리스너가 연결된 요소를 의미함 parent
부모요소

🍒 이벤트 위임

앞에서 우리는 이벤트의 흐름을 통해 이벤트 리스너가 없는 요소의 이벤트가 발생했을 때도 해당 요소에 접근 할 수 있다는 것을 알게 되었습니다.

이를 이용해 이벤트 리스너가 없어도 마치 리스너가 있는 것 처럼 사용 할 수 있습니다

  • 자식 요소에게만 할 수 있음 (부모 요소 -> 자식 요소)
  • 테크닉이라고 볼 수 있음

🍒 7. 이벤트의 this

이는 event.currentTarget 속성의 참조값과 유사합니다.

만약 이벤트 리스너 함수를 화살표 함수로 쓴다면 this 가 가리키는 대상이 달라진다는 점에 유의하세요.
this 찍으면 window가 나옴...
자신이 가지고 있는 바로 위의 scope를 참조함(부모 scope)
이벤트리스너 바로 바깥에 있는 스코프? 전역 스코프가 되죠. 그래서 window가 나오는 것입니다.

  • for each 문? 이벤트 위임?
    이벤트 위임이 좀 더 효율적인 코드
    addeventlistner가 딱 한번만 발생할 수 있기 때문
profile
UX디자인을 배우다 코딩의 매력에 흠뻑빠져 프론트엔드 개발자가 되고자 하는 코린이

0개의 댓글