Browser_DOM_API
#
DOM API- 정적인 웹페이지를 동적으로 변경하기 위한 방법
- 메모리 상에 존재하는 DOM 을 변경하는 것
- DOM 의 객체에 접근하고 수정할 수 있는 메서드와 프로퍼티
API(web or XML page) = DOM + JS(scripting language)
- DOM 은 프로그래밍 언어와 독립적으로 디자인 되었음
#
attribute 와 property 의 차이#
attributehtml 문서에서 elements 에 추가적인 정보를 넣을 때 사용되는 요소
- 정적임
<div class= ‘my-class’>
#
propertyHTML DOM 안에서 attribute 를 가리키는 표현
- 동적임
user 가 체크박스에 체크를 하면 attribute 는 변하지 않지만 property 는 checked 로 변한다.
지금까지 속성과 프로퍼티를 같다고 생각했었는데, 다른 맥락인 것을 처음 알게 되었습니다.
#
data typesnode 의 표현
- nodes ->
element
s - node 의 arrays ->
nodeList
s (element
s) - attribute 노드들 ->
attribute
s
#
document브라우저가 불러온 웹 페이지를 나타냄.
- 페이지 콘텐츠(DOM tree)의 기본 진입점
- 페이지 내 무엇이든 변경/추가 가능
- 자바스크립트로 제어 가능
#
인터페이스- HTML 문서는
HTMLDocument
인터페이스를 구현함 Document
는Node
와EventTarget
인터페이스를 상속함
흥미롭게 본 object
- Document.visibilityState
- Document.readyState
#
elementDOM API 에 멤버에 의해 return 된 element 또는 element type 의 node
document.createELement()
의 반환값
#
nodeListelements 의 배열
- index 를 통해 접근 가능
list.item(1)
nodeList 의 methodlist[1]
array syntax
#
attributecreateAttribute()
#
namedNodeMaparray 와 유사하지만 items 은 name 또는 index 에 의해 접근 가능
item()
methodnamedNodeMap
에 item 추가 / 삭제 가능
#
DOM InterfaceHTML FROM element 는 HTMLFormElement
interface 로 부터 name
property 를 얻고,
className
property 는 HTMLElement
interface 로 부터 얻는다.
그리고 두 property 는 모두 form object 안에 있다.
- object 는 다른
interface
s 와 연관되어 있다.
#
getElement, querySelector 로 요소 검색하기상대 위치를 이용하지 않으면서 웹 페이지 내에서 원하는 요소 노드에 접근할 수 있다.
#
document.getElementById(id)브라우저는 스크립트의 네임스페이스와 DOM 의 네임스페이스를 공유한다.
따라서 아래처럼, id 를 따서 만들어진 전역변수 요소 접근하고자 한다면, 스크립트의 전역변수와의 이름 충돌 가능성이 있기 때문에
document.getElementById
를 사용하는 것이 좋다.문서 내 요소의
id
속성값을 중복사용하면, 메서드 내 동작 예측이 불가능하여 임의 요소가 반환된다.document
객체에서만getElementById
를 호출 할 수 있다.
#
elem.querySelectorAll(css)elem
의 자식 요소 중 주어진 CSS 선택자에 대응하는 요소 모두를 반환함.
- CSS 선택자의 가상 클래도 사용 가능
document.querySelectorAll(':hover')
- 마우스 포인터가 hover 상태 요소들을 담은 컬렉션을 반환.
#
elem.querySelector(css)CSS 선택자에 대응하는 요소 중 첫 번째 요소 반환
elem.querySelectorAll(css)[0]
과 동일 하지만 모든 요소를 검색하지 않는 다는 점에서 빠르다.
#
elem.matches(css)Boolean
: elem
이 CSS 선택자와 일치하는지 판단.
#
elem.closest(css)elem
자기 자신을 포함하여 CSS 선택자와 일치하는 가장 가까운 조상 요소를 찾는다.
- DOM 트리를 한단계씩 거슬러 올라가며 찾음
- 일치하는 요소를 찾으면 검색을 중단하고 해당 요소를 반환.
#
elem.getElementsBy*태그나 클래스 등을 이용해 원하는 노드의 컬렉션(복수)을 반환한다.
querySelector
가 더 편리하고 문법도 짧기 때문에,getElementsBy*
는 현재 잘 쓰이지 않음elem.getElementsByTagName(*)
elem.getElementsByClassName(className)
document.getElementsByName(name)
- 문서 전체를 대상으로 검색 수행
- 검색기준은
name
속성 값이다.
#
살아있는 컬렉션#
getElementBy*살아있는 컬렉션 반환
- 문서에 변경이 있을 때마다 컬렉션이 자동 갱신되어 최신의 상태를 유지한다.
#
querySelectorAll정적인 컬렉션 반환
- 컬렉션이 한 번 확정되면 늘어나지 않는다.
- 조상(ancestor) 요소
부모 요소, 부모 요소의 부모 요소 등 DOM 트리에서 특정 요소의 상위에 있는 요소
#
노드의 부모 자식 관계를 확인하는 메서드elemA.contains(elemB)
- elemA 가 elemB 의 조상일 때
elemA==elemB
TODO MDN 명세서 읽어보기
#
주요 노드 프로퍼티앞서 설명한 DOM Interface 에서 확장된 설명이다.
- DOM 노드는 종류에 따라 각각 다른 프로퍼티를 지원한다.
- 그런데 모든 DOM 노드는 공통조상으로 만들어지기 때문에, 공통 프로퍼티와 메서드가 존재한다.
EventTarget
루트의 추상(abstract) 클래스Node
추상(abstract) 클래스parentNode
,nextSibling
,childNodes
등의 주요 탐색 트리 기능 제공- Node 를 상속받는 클래스들
Text
클래스 → 텍스트 노드Element
클래스 → 요소 노드Comment
클래스 → 주석 노드
Element
DOM 요소를 위한 클래스nextElementSibling
,children
getElementsByTagName
,querySelector
SVGElement
,XMLElement
,HTMLElement
클래스의 베이스 역할
HTMLELement
HTML 요소 노드의 베이스 역할 클래스- HTMLElement 를 상속받는 클래스
HTMLInputElement
input 태그 요소를 위한 클래스HTMLBobyElement
body 태그 요소를 위한 클래스HTMLAnchorElement
a 태그 요소를 위한 클래스
- HTMLElement 를 상속받는 클래스
등.. 특정 노드에서 사용할 수 있는 프로퍼티와 메서드는 상속을 기반으로 결정된다.
conosle.log(elem)
- 요소의 DOM 트리 출력
conosle.dir(elem)
- 요소를 DOM 객체처럼 취급하여 출력
- 프로퍼티를 확인하기 쉽다.
#
명세서에서 쓰이는 IDL (Interface Description Language)#
nodeType 프로퍼티- DOM 노드의 타입을 알아내고자 할 때
- readonly
elem.nodeType == 1
요소 노드elem.nodeType == 3
텍스트 노드elem.nodeType == 9
문서 객체
- 모던 자바스크립트에서는
instanceof
나 클래스 기반의 테스트를 이용한다. - nodeType 이 쓸 때가 더 간단할 때 사용하곤 한다.
#
nodeName 과 tagName 으로 태그 확인하기tagName
요소 노드에만 존재nodeName
모든 노드에 존재- 대상: 요소 노드 →
tagName
역할수행 - 대상: 텍스트노드, 주석노드 → 노드 타입을 나타내는 문자열 반환
- 대상: 요소 노드 →
#
innerHTML- 요소 안의 HTML 을 문자열 형태로 가져오거나 수정가능
- innerHTML 안에 script 태그를 삽입하면 html 일부가 되긴 하지만 실행되지 않는다.
#
innerHTML += 유의점innerHTML +=
은 추가가 아니라 내용을 덮어씀
- 기존 내용 삭제
- 기존 내용과 새로운 내용을 합친 새로운 내용을 씀
부작용
- 이미지나 리소스가 전부다시 불러와짐
- input 태그에서 사용자가 입력한 값이 사라짐
#
outerHTML요소의 전체 HTML.
outerHTML
은 DOM 안의 요소를 교체한다.- 요소를 DOM 에서 제거하고 새로운 HTML 조각을 넣는다.
- 문서에서
<div>
삭제 - 새로운 HTML 조각을 삭제한 공간에 삽입
- div 에는 여전히 기존 값이 저장되어 있고, 새로운 HTML 조각은 저장되어 있지 않음
새로운 HTML 조각을 참조하려면 다시 DOM 쿼리 메서드를 사용한다.
#
nodeValue / data : 텍스트 노드 내용 조작innerHTML
은 요소 노드에만 사용할 수 있다.
텍스트 노드와 같은 다른 타입의 노드에는 nodeValue
, data
를 사용할 수 있다.
- 두 프로퍼티는 아주 유사하고, 실무에서도 구분없이 사용한다. 그러나 명세서 상 작은 차이가 있다고 한다.
#
textContent 텍스트 조작- 사용하는 문자열에 태그를 넣어도 문자열 그대로 저장된다
- 사용자의 입력값이 HTML 에 침투하는 것을 막을 수 있다.
#
hiddenDOM 프로퍼티 요소를 보여줄지 말지를 지정
style="display:none"
와 기술적으로 동일하다.
#
value<input>``<select>``<textarea>
의 값이 저장됨.
- 대응되는 클래스 :
HTMLInputElement
HTMLSelectElement
#
href<a href="...">
의 값이 저장됨
- 대응되는 클래스 :
HTMLAnchorElement
#
idid
속성 값이 저장됨. 모든 요소 노드에서 사용가능
- 대응되는 클래스 :
HTMLElement
#
속성과 프로퍼티문맥 | 타입 | 이름 대소문자 구분 | |
---|---|---|---|
속성 | HTML 문서 | 문자열 | X |
프로퍼티 | DOM 객체 | 모든타입 | O |
#
커스텀 DOM 프로퍼티prototype 으로 모든 요소에서 사용할 수 있는 메서드를 추가할 수 있다.
#
HTML 속성브라우저 HTML 파싱 : DOM 객체를 만들 때, HTML 표준 속성을 이용해 DOM 프로퍼티를 만든다.
- 대소문자를 가리지 않음
- 속성값은 항상 문자열 프로퍼티는 문자열이 아닐 수 있다
요소가
id
같은 표준 속성 →id
표준속성의 프로퍼티가 생성- 비 표준 속성 → 프로퍼티 생성 🅧
#
비표준 프로퍼티 사용elem.hasAttribute(name)
속성 존재 여부 확인elem.getAttribute(name)
속성값을 가져옴elem.setAttribute(name, value)
속성 값을 변경/추가elem.removeAttribute(name)
속성값을 지움elem.attributes
모든 속성값 읽기
#
프로퍼티-속성 동기화input.value
처럼 동기화가 속성 → 프로퍼티 방향으로만 일어나는 예외상황
유저의 어떤 행동 때문에 value 가 수정되었는데, 수정 전의 원래 값으로 복구하고 싶은 경우, 속성에 저장된 값을 가지고 오면 된다.
#
DOM 프로퍼티 값의 타입- 속성값 → 항상 문자열
- 프로퍼티값
- 항상 문자열이 아닐 수 있다.
- 대부분 → 문자열
프로퍼티값이 문자열 이더라도, 속성값과 다를 수 있다.
#
비표준 속성, dataset비표준 속성
- 사용자가 직접 지정한 데이터를 HTML 에서 JS 에서 사용해야 할 때
위 방식처럼 새 클래스
.order-state-new, .order-state-pending, order-state-canceled
를 추가/삭제 하는 것보다
쉽게 상태를 바꿀 수 있다.
data-*
속성#
- 비표준 속성이 나중에 표준으로 등록되는 예기치 못한 문제가 발생할 수 있음
- data- 로 시작하는 속성 전체는 개발자가 용도에 맞게 사용하도록 예약됨.
- 커스텀 데이터를 안전하고 유효하게 전달함
- 읽기/수정 이 가능하다.
- 속성이 수정되면 CSS 가 해당 뷰를 자동으로 업데이트 해준다.
data-order-state
은 카멜 표기법을 사용해dataset.orderState
으로 변환
#
문서 수정하기#
예제: 메시지 보여주기HTML 을 이용한 메시지 창
JS 를 이용해 창을 만드는 방법. 스타일은 이미 존재한다고 가정.
#
요소 생성- Element Node →
document.createElement(tag)
- Text Node →
document.createTextNode(text)
메시지 생성
#
삽입 메서드JS 노드 삽입 메서드
node.append(노드/문자열)
node.prepend(노드/문자열)
node.before(노드/문자열)
node.after(노드/문자열)
node.replaceWith(노드/문자열)
node 를 새로운 노드나 문자열(TextNode 로)로 대체함
- 매개 변수: 복수의 노드/문자열 삽입 가능
- 태그가 담긴 문자열 ->
<``>
는 이스케이프 처리됨
#
elem.insertAdjacentHTML / Text / Element (where, html)#
whereelem
기준 상대위치
- 두개의 단어로 구성
- 뒷단어 : begin → 시작태그, end → 닫는태그
- 앞단어 : 뒷단어를 기준으로 before, after
'beforebegin'
: elem 가 열리기 전html(text/Element)
삽입'afterbegin'
: elem 가 열리고,html(text/Element)
삽입'beforeend'
: elem 가 닫히기 전,html(text/Element)
삽입'afterend'
: elem 가 닫히고,html(text/Element)
삽입
#
htmlHTML 문자열
#
노드 삭제 node.remove()요소를 다른 곳으로 옮길 때
모든 노드 삽입 메서드는,
- 자동으로 기존에 있던 노드를 삭제하고 새로운 곳으로 노드를 옮긴다.
#
elem.cloneNode(boolean) 노드 복제boolean
true
elem 의 속성전부와, 자손 요소 전부 복사false
후손 노드 복사 없이 elem 만 복사
기존 메시지 창과 유사한 메시지 창을 하나 더 띄우고 싶을 경우
#
DocumentFragment- 특별한 DOM 노드 타입
- 여러 노드로 구성된 그룹을 감싸 다른 곳으로 전달하게 하는 Wrapper 처럼 동작
- DocumentFragment 에 다른 노드들을 추가한다.
- DocumentFragment 를 문서 어딘가에 삽입한다.
- DocumentFragment 는 사라짐. DocumentFragment 에 추가한 노드만 남음
노드가 담긴 배열을 직접 만들어 반환할 수 있기 때문에 DocumentFragment
를 직접 사용할 일은 흔치 않다.
- 웹컴포넌트 template 요소 같이
DocumentFragment
기반 문법에서 다시 다룬다.
#
구식 삽입 / 삭제 메서드아래 메서드들은 모두 삽입/삭제한 노드를 반환하지만, 그 값을 사용할 일이 거의 없다.
#
parentElem.appendChild(node)parentElem 의 마지막 자식으로 node 추가
#
parentElem.insertBefore(node, nextSibling)node 를 parentElem 안의 nextSibling 앞에 추가
#
parentElem.replaceChild(node, oldChild)parentElem 의 자식 노드 중 oldChild 를 node 로 교체
#
parentElem.removeChild(node)node 가 parentElem 의 자식 노드라는 가정하에 parentElem 에서 node 를 삭제
#
document.write(HTML) 에 대한 첨언웹페이지에 뭔가를 더할 때 쓰는 아주 오래된 메서드
html 형식의 문자열을 동적으로 만들어 사용할 수 있다.
페이지를 불러오는 도중에만 작동함
페이지 로드 후, 호출하면 기존 문서내용이 사라짐
브라우저 HTML 파싱 중 (DOM 구조가 완성되기 전)
document.write(HTML)
을 만나면 (페이지에 내용이 삽입되면, DOM 조작이 아님)- 텍스트 형식의 HTML 을 마치 원래 페이지에 있었던 것 마냥 해석함 (빠름)
#
Reference & Comment- https://developer.mozilla.org/ko/docs/Web/API/Document_Object_Model/%EC%86%8C%EA%B0%9C
- https://developer.mozilla.org/ko/docs/Web/API/Document_Object_Model
- https://ko.javascript.info/searching-elements-dom
- https://ko.javascript.info/basic-dom-node-properties
- https://ko.javascript.info/dom-attributes-and-properties
- https://ko.javascript.info/modifying-document