[JS] DOM

김다빈·2023년 8월 12일
0

자바스크립트

목록 보기
12/36
post-thumbnail

🚩 DOM (Document Object Model, 문서 객체 모델)

  • HTML 문서를 객체로 표현한 것
  • JS에서 HTML을 제어할 수 있도록 한다.

🚩 노드(Node) vs 요소(Element)

노드

  • HTML 요소, 텍스트, 주석 등 모든 것을 의미

요소

  • HTML 요소를 의미

HTML

<div class="parent">
  <!-- 주석 -->
  <div class="child">1</div>
  텍스트1
  <div class="child">2</div>
  텍스트2
</div>

JS

const parent = document.querySelector('.parent')

//부모 요소의 모든 자식 노드 확인
console.log(parent.childNodes)

//부모 요소의 모든 자식 요소 확인
console.log(parent.children)

출력결과

  • 노드를 확인하면 요소 + 주석이나 일반 텍스트도 자식으로 확인되는 반면, 요소를 확인하면 HTML 태그로 작성되어있는 요소만 확인할 수 있다.

➡️ 즉, 노드는 요소보다 상위 개념이다.

🚩 검색과 탐색

document.getElementById()

  • HTML id 속성 값으로 검색한 요소를 반환
  • 만약 여러 요소가 검색되면 가장 먼저 찾은 요소만 반환
  • 검색 결과가 없으면 null 을 반환

HTML

<div class="parent">
  <!-- 주석 -->
  <div class="child">1</div>
  텍스트1
  <div id="child2" class="child">2</div>
  텍스트2
</div>

JS

const el = document.getElementById('child2')
console.log(el) //<div id="child2" class="child">2</div>

document.querySelector()

  • CSS 선택자로 검색한 요소를 하나 반환
  • 만약 여러 요소가 검색되면 가장 먼저 찾은 요소만 반환
  • 검색 결과가 없으면 null 을 반환
const el = document.querySelector('.child:first-child')
console.log(el) //<div class="child">1</div>

document.querySelectorAll()

  • CSS 선택자로 검색한 모든 요소를 Nodelist로 반환
  • Nodelist 객체는 .forEach() 사용 가능
const nodeList = document.querySelectorAll('.child')
console.log(nodeList)
//<div class="child">1</div>
//<div id="child2" class="child">2</div>

nodeList.forEach(el => console.log(el.textContent))
//1
//2

N.parentElement()

  • N은 노드를 의미
  • 노드의 부모 요소를 반환
const el = document.querySelector('.child')
console.log(el.parentElement)
//<div class="parent">
//  <!-- 주석 -->
//  <div class="child">1</div>
//  텍스트1
//  <div id="child2" class="child">2</div>
//  텍스트2
//</div>

E.closest()

  • E은 노드를 의미
  • 자신을 포함한 조상 요소 중 CSS 선택자와 일치하는 가장 가까운 요소를 반환
  • 요소를 찾지 못하면 null 을 반환
const el = document.querySelector('.child')

console.log(el.closest('div')) //<div class="child">1</div>
console.log(el.closest('body')) //<body> ... </body>
console.log(el.closest('.hello')) //null

N.previousSibling / N.nextSibling

  • 노드의 이전 또는 다음 형제 노드를 반환
const el = document.querySelector('.child')

console.log(el.previousSibling) //#text (줄바꿈)
console.log(el.nextSibling) //"텍스트1"

E.previousElementSibling / E.nextElementSibling

  • 요소의 이전 또는 다음 형제 요소를 반환
const el = document.querySelector('.child')

console.log(el.previousElementSibling) //null
console.log(el.nextElementSibling) //<div id="child2" class="child">2</div>

E.children

  • 요소의 이전 또는 다음 형제 요소를 반환
const parent = document.querySelector('.parent')

console.log(parent.children)
//HTMLCollection [
//<div class="child">1</div>
//<div id="child2" class="child">2</div>
//]

E.firstElementChild / E.lastElementChild

  • 요소의 첫 번째 또는 마지막 자식 요소를 반환
const parent = document.querySelector('.parent')

console.log(parent.firstElementChild)//<div class="child">1</div>
console.log(parent.firstElementChild)//<div id="child2" class="child">2</div>

🚩 생성, 조회, 수정

document.createElement()

  • 메모리에만 존재하는 새로운 HTML 요소를 생성해서 반환
  • JS에서 요소를 생성하면 실제 HTML 문서에 바로 추가되는 것이 아님.
    후에 다른 명령어를 통해 실제 문서에 추가해주는 작업을 따로 해야한다.
const divEl = document.createElement('div')
const inputEl = document.createElement('input')

E.prepend() / E.append()

  • 노드를 요소의 첫 번째 또는 마지막 자식으로 삽입한다.
const parentEl = document.querySelector('.parent')

const el = document.createElement('div')
el.textContent = 'HELLO~'

parentEl.prepend(new Comment(' 주석 '))
parentEl.append(el)
parentEl.append('Text!')
// parentEl.append(el, 'Text!')
// 동일한 메소드를 사용하면 한 번에 작성할 수도 있다.

E.remove()

  • 요소를 제거
const el = document.querySelector('.child')
el.remove()

ㄴ 이때, child 클래스를 갖는 요소 중 가장 먼저 찾은 요소만 삭제된다.

E.insertAdjacentElement()

  • 대상 요소의 지정한 위치에 새로운 요소를 삽입
    대상 요소.insertAdjacentElement('위치', 새로운 요소)

위치

<--! beforebegin -->
<div class="child">
  <--! afterbegin -->
  Content!
  <--! beforeend -->
</div>
<--! afterend -->

JS

const childEl = document.querySelector('.child')
const newEl = document.createElement('span')
newEl.textContent='Hello~'

childEl.insertAdjacentElement('beforebegin', newEl)
//newEl는 <div clas='child'> 태그의 시작 전에 삽입된다.

출력 결과

  • div 내부에 삽입하는거라면 굳이 E.insertAdjacentElement() 를 쓰지 않고 prepend(), append() 를 사용할 수도 있음.

N.insertBefore()

  • '부모 요소'의 자식인 '참조 노드'의 이전 형제로 '노드'를 삽입
    부모 요소.insertBefore(노드, 참조 노드)
const parentEl = document.querySelector('.parent')
const childEl = document.querySelector('.child')
const newEl = document.createElement('span')
newEl.textContent='Hello~'

parentEl.insertBefore(newEl, childEl)
//newEl는 <div clas='child'> 태그의 시작 전에 삽입된다.
  • 부모 노드, 기준이 될 '참조 노드', 실제 삽입할 노드 순으로 작성하면 쉽게 작성할 수 있다.

N.textContent()

  • 노드의 모든 텍스트를 얻거나 변경
const el = document.querySelector('.child');
console.log(el.textContent) //"1"

el.textContent = '7';
console.log(el.textContent) //"7"

E.innerHTML()

  • 요소의 모든 HTML 내용을 문자로 얻거나 새로운 HTML을 지정
  • 이때 HTML 내용은 꼭 ' '따옴표 혹은 백틱으로 묶어줘야 함!!!!
const el = document.querySelector('.parent');
console.log(el.innerHTML)
//<div class="child">1</div>
// <div id="child2" class="child">2</div>

el.innerHTML = '<span style="color : red;">HELLO~</span>';
console.log(el.textContent) //HELLO~

E.dataset()

  • 요소의 각 'data-' 속성 값을 얻거나 지정 (HTML 요소에 자바스트립트의 데이터를 저장할 때 사용)
  • 객체 데이터를 저장할 때는 JSON.stringify() 메소드를 사용해서 저장해야 데이터가 망가지지 않고 저장된다. 추후에 다시 해당 데이터를 사용할 때는 JSON.parse() 메소드를 사용하면 된다.
const el = document.querySelector('.child');
const str = 'Hello World';
const obj = { 'a' : 1, 'b' : 2 };

el.dataset.helloWorld = str;
el.dataset.object = JSON.stringify(obj);

console.log(el.dataset.helloWorld); //'Hello World' 문자열로 출력
console.log(el.dataset.object); //'{ 'a' : 1, 'b' : 2 }' 문자열로 출력
console.log(JSON.parse(el.dataset.object)); //{ 'a' : 1, 'b' : 2 } 객체로 출력

E.tagName()

  • 요소의 태그 이름을 반환
const parentEl = document.querySelector('.parent');
const childEl = document.querySelector('.child');
const el = document.createElement('span');

console.log(parentEl.tagName); //DIV
console.log(childEl.tagName); //DIV
console.log(el.tagName); //SPAN
console.log(document.body.tagName); //BODY

E.id()

  • 요소의 id 속성 값을 얻거나 지정
const el = document.querySelector('.child');
console.log(el.id); //'' 빈 문자 = 아무런 내용이 출력되지 않음

el.id = 'child1';
console.log(el.id); //'child1'

E.className()

  • 요소의 class 속성 값을 얻거나 지정
  • 요소에 클래스를 지정하는 것과 관련해서는 뒤에 나오는 classList 메소드 를 더 많이 사용하게 될 것
const el = document.querySelector('.child');
console.log(el.className); //'child'

el.className += ' child1 active';
console.log(el.className); //'child child1 active'

E.classList()

  • 요소의 class 속성 값을 제어
    .add() : 새로운 값 추가
    .remove() : 기존 값 제거
    .toggle() : 해당하는 값이 있으면 제거, 없으면 추가
    .contains() : 값이 있는지 확인
const el = document.querySelector('.child');

el.classList.add('active');
console.log(el.classList.contains('active')); //true

el.classList.remove('active');
console.log(el.classList.contains('active')); //false

el.addEventListener('click', () => {
  el.classList.toggle('active');
  console.log(el.classList.contains('active'));
});
//el 요소를 클릭했을 때 이벤트를 발생시킬건데 그 내용은
//el 요소에 active 클래스가 있으면 해당 클래스를 제거하고, 콘솔에 active 라는 클래스가 있는지 없는지를 불린형으로 반환해라.
//만약 el 요소를 여러 번 클릭하면 active 클래스가 생겼다 없어졌다를 반복할거고, 콘솔에도 true/false 값이 번갈아가며 출력되겠지.

E.style()

  • 요소의 style 속성(인라인 스타일의 CSS 속성 값)을 얻거나 지정
  • 인라인 스타일로 css 속성을 지정해주게되면 우선순위가 1000점으로 거의 우선시되기 때문에 이 방법을 통해 style 속성을 제어하는 것은 주의가 필요함!
const el = document.querySelector('.child');

//개별 지정
el.style.width = '100px';
el.style.fontSize = '20px';
el.style.backgroundColor = 'green';

//한 번에 지정
Object.assign (el.style, {
  width = '100px',
  fontSize = '20px',
  backgroundColor = 'green'
})
  • 한 번에 작성하고 싶다면 Object.assign() 메소드 사용해서 객체 데이터 방식으로 작성할 수 있다.
    (css 작성하는 방식이 자스 입장에서 봤을 때 보면 객체긴 함...)

window.getComputedStyle()

  • 요소에 적용된 스타일 객체 반환 (= 요소에 적용된 css 스타일을 확인하고 싶을 때 사용. 지정은 안됨)
const el = document.querySelector('child');
const styles = window.getComputedStyle(el);

console.log(styles.width); //100px
console.log(styles.fontSize); //20px
console.log(styles.backgroundColor); //rgb(0, 128, 0)
console.log(styles); //el 요소에 적용된 모든 css 내용이 출력

E.getAttribute() 와 E.setAttribute()

  • 요소에서 특정 속성 값을 얻거나 반환
const el = document.querySelector('child');

el.setAttribute('title', 'Hello World');
console.log(el.getAttribute('title')); //'Hello World'

E.hasAttribute() 와 E.removeAttribute()

  • 요소에서 특정 속성 값을 확인하거나 제거
const el = document.querySelector('child');

console.log(el.hasAttribute('class'); //true

el.removeAttribute('class');
console.log(el.hasAttribute('class'); //false

🚩 크기와 좌표

window.innerWidth / window.innerHeight

  • 현재 화면(뷰포트)의 크기를 얻습니다.
console.log(window.innerWidth); //977
console.log(window.innerHeight); //626

window.scrollX / window.scrollY

  • 페이지의 좌상단(0,0)을 기준으로 현재 화면(뷰포트)의 수평/수직 스크롤 위치를 얻는다.
console.log(window.scrollX); //0
console.log(window.scrollY); //216

window.scrollTo() / E.scrollTo()

  • 지정된 좌표로 대상(화면, 스크롤 요소)를 스크롤한다.
    대상.scrollTo(x좌표, y좌표)
    대상.scrollTo({ left : X, top : Y, behavior : 'smooth' })
const parentEl = document.querySelector('.parent');

setTimeOut(() => {
  parentEl.scrollTo({
    left : 0,
    top : 500,
    behavior : 'smooth'
  })
}, 1000)
  • setTimeOut 함수를 통해 1초 뒤에 함수가 실행되도록 하였다.
    새로고침하고 1초가 지나면 스크롤이 어디에 위치해있던지 (0,500)의 위치로 이동하게 되는데 이때, bahavior 에 따라 부드럽게 움직인다.

E.clientWidth() / E.clientHeight()

  • border를 제외한 요소의 크기를 얻는다.
  • 스크롤바가 있으면 스크롤바 영역도 제외한 크기를 얻는다.
  • 잘 사용하게 되지는 않음

E.offsetWidth() / E.offsetHeight()

  • border를 포함한 요소의 크기를 얻는다.
  • 요소의 크기를 얻을 때 사용하기 좋음

E.scrollLeft / E.scrollTop

  • 스크롤 요소의 좌상단(0,0)을 기준으로 현재 스크롤 요소의 수평/수직 스크롤 위치를 얻는다.
window.parentEl = document.querySelector('.parent');
//const 변수가 아닌 window 객체의 속성으로 값을 할당하는 이유는 window가 전역객체이기 때문이다
//화면(뷰포트)에서 parnet 요소에 접근하려면 해당 요소를 window 객체에 연결해주어야 한다.
console.log(parentEl.scrollLeft, parentEl.scrollTop); //0

E.offsetLeft / E.offsetTop

  • 페이지의 좌상단(0,0)을 기준으로 요소의 위치를 얻는다.
    => 잘 이해가 안됨... 나중에 쓸일이 있을 때 다시 찾아보자

getBoundingClientRect()

  • border를 포함한 요소의 크기와 화면에서의 상대 위치 정보를 얻는다.
  • 현재 화면에서 스크롤이 어디에 위치해있는지에 따라 해당 요소의 위치(x좌표, y좌표 등)이 달라진다.
const parentEl = document.querySelector('.parent');
const childEl = document.querySelector('.child');

console.log(parentEl.getBoundingClientRect());
console.log(childEl.getBoundingClientRect());
profile
Hello, World

0개의 댓글

관련 채용 정보