[240520] 39장 DOM (3)

6. DOM 조작

  • DOM 조작은 DOM 에 새로운 노드를 추가, 삭제, 교체하는 것을 말함
  • DOM 에 변화가 생기면 리플로우와 리페인트가 발생한다.
  • DOM 성능 최적화를 위해 주의해서 다루어야 함

1. innerHTML

  • Element.prototype.innerHTML
  • 요소 노드의 HTML 마크업을 취득하거나 변경함
  • 요소노드의 콘텐츠 영역 (시작태그와 종료 태그 사이) 내에 포함된 모든 HTML 마크업을 문자열로 반환
  • innderHTML 프로퍼티에 문자열을 할당하면 요소 노드의 모든 자식 노드가 제거되고 할당한 문자열에 포함되어 있는 HTML 마크업이 파싱되어 DOM 에 반영
// 노드 추가
$fruits.innerHTML += '<li>Banana</li>';

// 노드 교체
$fruits.innerHTML = '<li>Banana</li>';

// 노드 삭제
$fruits.innerHTML = ''; 
  • 입력 받은 데이터를 innerHTML 프로퍼티에 할당하는 것은 크로스 사이트 스트립팅 공격에 취약하므로 위험하다.
  • HTML5 에는 innerHTML 프로퍼티로 삽입된 script 요소는 실행하지 않는다.
    • DOMPurify 라이브러리의 sanitize 사용 권장 (공격 예방)
  • 삽입할때 추가하는거만 그리는게 아니라 자식 요소 다 새로 그리는거임
  • 삽입될 위치 지정할 수 없음

2. insertAdjacentHTML 메서드

  • Element.prototype.insertAdjacentHTML(position, DOMString)
  • 기존 요소 제거하지 않으면서 위치를 지정해 새로운 요소 삽입

  • 크로스 사이트 스크립팅 공격에 취약

3. 노드 생성과 추가

const $fruits = document.getElementById('fruits');

// 1. 요소 노드 생성
const $li = document.createElement('li');

// 2. 텍스트 노드 생성
const textNode = document.createTextNode('Banana');

// 3. 텍스트 노드를 $li 요소 노드의 자식 노드로 추가
$li.appendChild(textNode);

// 4. $li 요소 노드를 #fruits 요소 노드의 마지막 자식 노드로 추가
$fruits.appendChild($li);

4. 복수의 노드 생성과 추가

  • foreach 로 DOM 에 매번 추가하면 리플로우와 리페인트가 매번 실행된다.
  • 가급적 줄이는 편이 좋기 때문에, 자식 요소에 새로운 요소를 추가하고 마지막에 DOM 에 적용하는 것이 좋다.
  • 이때, DocumentFragment 노드를 활용하면 좋다.
    • DOM 에 추가하면 자신은 제거되고 자신의 자식 노드만 DOM 에 추가되기 때문

5. 노드 삽입

  • 마지막 노드로 추가
    • Node.prototype.appendChild 메서드는 인수로 전달 받은 노드를 자신을 호출한 노드 마지막 자식 노드 DOM 에 추가함, 위치 지정 X
  • 지정한 위치에 노드 삽입
    • Node.prototype.insertBefore(newNode, childNode)
    • 첫번째 인수로 전달 받은 노드를 두 번째 인수로 전달 받은 노드 앞에 삽입한다.
    • 두 번째 인수는 자식 노드여야하며 아니면 DOMException 에러 발생

6. 노드 이동

  • appendChild, insertBefore 메서드 사용

7. 노드 복사

  • Node.prototype.cloneNode([deep: true false])
  • true 면 깊은 복사, 자손 노드가 포함된 사본 생성
  • 얕은 복사 자신만의 사본으로 생성

8. 노드 교체

  • Node.prototype.replaceChild(newChild, oldChild)
  • 첫 번째 매개변수 : 새로운 노드
  • 두 번째 매개변수 : 교체될 노드

9. 노드 삭제

  • Node.prototype.removeChild(child)
    • 자식 노드여야함

어트리뷰트

1. 어트리뷰트 노드와 attributes 프로퍼티

  • 글로벌 어트리뷰트 ( id, class, style, title, lang, .. )
  • 이벤트 핸들러 어트리뷰트 (onclick, onchange .. )
  • 어트리뷰트당 하나의 어트리뷰트 노드 생성
  • 모든 어트리뷰트 노드의 참조는 유사 배열 객체이자 이터러블인 NamedNodeMap 객체에 담겨서 요소 노드의 attributes 프로퍼티에 저장된다.
    • getter 만 존재 ( 읽기 전용 )

2. HTML 어트리뷰트 조작

  • Element.prototype.getAttribute/setAttribute
  • Element.prototype.hasAttribute
  • Element.prototype.removeAttribute

3. HTML 어트리뷰트 vs DOM 프로퍼티

  • DOM 프로퍼티들은 HTML 어트리뷰트 값을 초기값으로 가지고 있다.
  • HTML 어트리뷰트는 DOM 에서 중복 관리되는 것처럼 보임
    • 요소 노드의 attributes 프로퍼티에서 관리하는 어트리뷰트 노드
    • HTML 어트리뷰트에 대응하는 요소 노드의 프로퍼티 (DOM 프로퍼티)

→ 중복X , HTML 어트리뷰트의 역할은 HTML 요소의 초기 상태를 지정하는 것이다.

어트리뷰트 노드

  • 초기상태 관리
  • 사용자의 입력에 의해 상태가 변경되어도 변하지 않음
  • getAttribute/setAttribute 메서드를 사용하면 변경 가능

DOM 프로퍼티

  • 사용자가 입력한 최신 상태는 요소노드의 DOM 프로퍼티가 관리
  • 언제나 최신상태 유지
  • 입력에 관한거만 최신 상태 값 관리, 외에는 상관없이 어트리뷰트와 DOM 프로퍼티는 항상 동일한 값으로 연동

HTML 어트리뷰트와 DOM 프로퍼티의 대응 관계

  • 대부분 이름과 도일하게 1:1 대응
  • 몇개는 다른거 있음

DOM 프로퍼티 값의 타입

  • getArribute 메서드로 취득하면 언제나 문자열인데 DOM 은 아닐수도 있음 ( checked 이런거 )

4. data 어트리뷰트와 dataset 프로퍼티

  • 접두사에 data- 이름을 사용하면 사용자 정의 어트리뷰트와 자바스크립트간에 데이터 교환 가능
  • HTMLElement.dataset 프로퍼티로 취득 가능
  • 어트리뷰트 정보를 제공하는 DOMStringMap 객체는 카멜 케이스로 변환해서 프로퍼티 갖고 있음

스타일

1. 인라인 스타일 조작

  • HTMLElement.prototype.style
    • setter, getter 로 인라인 스타일 추가나 변경 가능
    • CSSStyleDeclaration 타입의 객체 반환
      • 다양한 CSS 프로퍼티 갖고 있음
      • 카멜 케이스 따름

2. 클래스 조작

  • class 어트리뷰트에 대응하는 DOM 프로퍼티는 className, classList 다
  • className 프로퍼티
    • setter , getter 존재
    • class 어트리뷰트 값 취득하거나 변경
    • 문자열로 반환하고 문자열로 할당
    • 공백으로 구분된 여러 개의 클래스 반환하기 어려움
  • classList 프로퍼티
    • class 어트리뷰트의 정보를 담은 DOMTokenList 객체 반환
      • 유사 배열 객체면서 이터러블이다.
      • forEach, entries, keys, values, supports 메서드 제공
      $box.classList.add('foo') 
      $box.classList.remove('foo') 
      $box.classList.item(0) // box
      $box.classList.contains('foo') // true , false
      $box.classList.replace('foo', 'blue') 
      $box.classList.toggle('foo') // 존재하면 제거, 존재하지 않으면 추가
    

3. 요소에 적용되어 있는 CSS 스타일 참조

  • style 프로퍼티는 인라인 스타일만 반환해서, 클래스나 상속을 통한 스타일은 참조할 수 없다.
  • getComputedStyle 메서드 사용해야함
// box 요소에 적용된 모든 CSS 스타일 담고 있는 CSSStyleDeclaration 객체 획득
const computedStype = window.getComputedStyle($box);

Categories:

Updated:

Leave a comment