- 돔 트리의 구조
- Document 객체는 브라우저가 불러온 웹 문서를 가리키며, 그 내부 컨텐츠들로의 진입점 역할을 한다. DOM 트리는 현재의 웹문서에 포함된 <body> 및 여타 문서 내 모든 컨텐츠들을 계층 구조로 나타내며, 이 Document 인터페이스는 DOM 트리 내부 컨텐츠들의 상태 정보를 얻거나 DOM 트리에 새로운 요소를 생성하는 등의 기능을 전역적으로 제공한다
-
1.
DOM 트리는 document 객체를 루트로 하여
<html> 아래 <head> & <body>, 그 아래 요소 노드 및 텍스트 노드, 공백 노드 등으로 구성된다.
DOM 트리의 각 구성 요소는 Node 객체가 되며,
노드.
속성
, 노드.메서드()
로 접근할 수 있다: - 2. DOM 트리 안의 Node 객체들에는 html 요소 노드(= Element 객체) 및 그에 딸린 텍스트 노드(html tag 내 텍스트)와 빈 노드(연속된 공백, 탭, 줄 바꿈), 속성 노드(html tag의 속성), 주석 노드 등이 있다:
-
3.
NodeList 객체는 일반적으로 부모요소.
children
과 같은 속성이나 document.querySelectorAll()
과 같은 메서드에 의해 반환되는 정적(및 동적) 노드 컬렉션으로서 유사배열 객체이다. 예컨대, 부모요소.children
에서 각 자식 요소들은 for .. of 문이나forEach()
와 같은 메서드로 반복할 수 있고, 배열에서와 같은 방식으로 접근할 수 있다:
html 문서 전체는 document 객체로 가져온다.
예컨데, document.title
은 웹 문서 및 탭의 제목을 가리키는데,
그때 그때 새로운 메시지 등을 알리는데 사용할 수 있다
←
이 문단에 마우스를 올리고 브라우저 창 제목표시줄의 현재 탭 제목을 보세요..
const doc_title= document.title // 현재 문서의 제목을 변수로 저장한다
document.querySelector('#title_change').addEventListener('mouseenter', () => document.title='다시 오셨네요 ^^'); // 마우스를 올리면; 문서 타이틀을 변경한다
document.querySelector('#title_change').addEventListener('mouseleave', () => document.title= doc_title); // 마우스를 내리면; 다시 원래 제목을 넣어준다
☞
여기서 <p> 태그 영역 전체는 p 요소 노드가 되며,
그 내부의 class= "para"
부분은 속성 노드,
텍스트 영역 부분은 텍스트 노드가 된다
←
html 태그의 시작 및 끝 부분 공백은 제외하고, 각 태그 앞/뒤의 연속적인 공백 문자는 '빈 노드'로 생성된다!
➥ 노드는 DOM 트리의 계층 구조상 지위만 아니라, 다른 노드를 기준으로 하는 위치로도 참조된다. 우선, Root 는 DOM 트리의 최상위 노드를 말하는데, html 문서에서의 최상위 노드는 언제나 html 노드이다. Child 는 현재 노드 밑 단계에 속한 노드들(= 자식 요소들)을, Parent 는 현재 노드를 포함하고 있는 상위 노드(= 부모 요소)를 가리킨다. 한편, Sibling 은 현재 노드와 동일한 단계에 위치하는 노드들(= 형제 요소들)을, Descendant 는 DOM 트리에서 하위 수준에 포함된 노드들(= 후손 요소들)을 가리킨다
✓
각 요소들은 . 연산자에 의한 체인 연결로 참조할 수 있지만,
요소 노드 사이에 있는 공백 노드의 존재로 인해 다루기에 불편하다.
그에 공백 노드를 제외한 요소만의 참조를 위한 속성도 준비되어 있지만(예컨대, 부모요소.children
),
역시 불편하여 실상은 요소의 id 나 class 를 쓰게 된다!
const el= document.querySelector('#my_container')
for (const child of el.children) { // el 내부 모든 자식 요소들로 루프를 돈다 ← children은 (텍스트 노드 등은 제외하고)요소 노드만을 대상으로 한다!
console.log(child.tagName) // el에 포함된 모든 태그명을 출력한다
}
☞
NodeList 컬렉션은 유사배열 객체이므로 for 문이나 forEach()
메서드로 반복하거나,
Array.from()
메서드를 써서 배열로 변환할 수도 있다.
나아가, entries()
, values()
, keys()
등의 메서드들도 사용할 수 있다!
✓
참고로, document.querySelectorAll()
은 호출 시점에서의 정적 노드 리스트를 가져오는 반면,
부모요소.children
은 돔의 변경 사항을 실시간으로 반영한다.
따라서, 노드 리스트에서 순회하거나, 그 길이(length
)를 가져와야 할 때는 이 점에 유의해야 한다!
- 돔 이벤트 호출: on 이벤트
-
이벤트명 앞에
on
을 붙여 해당 이벤트를 호출한다: 이벤트 대상.onclick / onwheel / onscroll / onvisibilitychange;
등.. ← 이벤트 제거는 이벤트 대상.onclick= null;
let time_pic= document.querySelector('#on_click_button')
function cPic() { // 이벤트 처리함수
let d= new Date()
alert("현재 시각: " + d.toLocaleString())
}
time_pic.onclick= cPic // Click 이벤트로 cPic() 함수를 호출한다
☞ 이벤트 처리함수 호출 시에는 일반 함수 호출과는 달리 함수명 뒤에 ()를 붙이지 않는다 ← 뒤에 괄호를 붙이게 되면; 이벤트 호출 버튼을 클릭하기 전에 먼저 함수 코드가 실행되어버린다!
✓
참고로, 최근에는 이 on 이벤트보다는
를 쓰는 것이 일반적이다.
타겟.addEventListener()
는 같은 리스너에 대해 다수의 핸들러 함수를 등록할 수 있다는 점,
제거 시에도 짝이 되는 removeEventListener()
가 존재한다는 점,
같은 이벤트 타입에 대해 손쉽게 복수의 이벤트 핸들러 함수를 등록할 수 있다는 점 등에서 on 이벤트에 비해 보다 유용하다!
- 돔의 컨텐츠 읽고쓰기
-
모든 html 요소는 요소.
textContent
속성으로 요소 내 (순수)텍스트를 가져오거나 쓸 수 있다. 한편, 요소.innerHTML
을 쓰면; (요소 내부에 html 코드가 포함되고, 분석된)텍스트 읽기 및 쓰기가 가능하고, 나아가, 요소.outerHTML
을 쓰면; (요소 자신까지 포함하는 html 코드가 포함되고, 분석된)텍스트 읽기 및 쓰기가 가능해진다:
* 경주 남산 날씨정보) 약간 흐림 (현재 23도)
➥
대상요소.insertAdjacentHTML('삽입위치', 'html코드')
는 주어진 html코드 를
대상요소를 기준으로 하는 삽입위치 값에 맞추어 삽입한다:
☞ 기존에 존재하고 있던 요소의 앞에 배치되면; 기존 요소들은 뒤로 밀려난다!
✓
사용 중인 모든 요소를 없애고 새로 파싱하는 innerHTML()
과는 달리,
이미 사용 중인 요소는 제외하고 새로 추가되는 요소에 대해서만 작업한다는 점에서 차이가 있는데,
당연히 돔 갱신 속도도 더 빠르다
←
참고로, 일반 텍스트는 insertAdjacentText()
메서드를 쓸 수도 있지만,
textContent
속성을 쓰는 것이 쉽고 간결하다!