본문 바로가기

JS/JavaScript

11. DOM

DOM(Document Object Model)

HTML(웹문서, 웹페이지) 문서를 객체 기반으로 표현한 것

 -> HTML문서에 작성된 내용을 트리구조(계층형)로 나타냈을 때 각각의 태그, text, commet 등을 Node라 한다.

 

* 계층형 구조 

     document : {
        DOCTYPE : html 
        HTML : {
            HEAD : {
                TITLE : { TEXT : "문서제목"}
                STYLE : {...} 
                META : {...}
            },
            BODY : {
                H1 : {TEXT : "제목", ATTRIBUTE : "속성"}
                COMMENT : {TEXT: 주석내용}
                DIV : {...}
            }
        }
     }

 

Node 확인하기 
부모 요소.parentNode 요소의 부모 노드 탐색하여 반환
자식 요소.childNodes 요소의 자식 노드 모두 반환(NodeList 형태)
요소.firstChild 첫번째 자식 노드 탐색하여 반환
요소.lastChild 마지막 자식 노드 탐색하여 반환
요소.childNodes[인덱스] 인덱스 x번째 자식 노드 탐색하여 반환
형제 요소.previousSibling 요소의 이전 형제 노드 반환
요소.nextSibling 요소의 다음 형제 노드 반환

 

   <ul id="test">
        <!-- Node 확인 테스트 주석 -->
        <li id="li1">1번</li>
        <li class="cls">2번</li>
        <li style="background-color: pink;">3번</li>
        <li><a href="#">4번</a></li>
    </ul>
    <button id="btn1">확인하기</button>
document.getElementById("btn1").addEventListener("click", function(){

    // #test의 자식 노드 모두 확인
    const testNodeList = document.getElementById("test").childNodes
    console.log("#test의 자식 노드 모두 확인")
    console.log(testNodeList)

    // 노드 탐색 
    const li1 = document.getElementById("li1")
    console.log("#li의 부모노드 탐색")
    console.log(li1.parentNode)

    // 노드 탐색 활용: #li1 부모의 배경을 orange로 변경 
    li1.parentNode.style.backgroundColor = "orange"

    // #li 부모 노드의 마지막에 "ABCD" 추가
    // 요소.append(요소/노드)
    li1.parentNode.append("ABCD")
})

 

 

 

Node와 Element의 차이 

- Node: 태그(요소 노드), 속성, 주석, 내용(텍스트 노드) 등 모두 표현

- Element: Node의 하위 개념으로 요소 노드만을 표현

Element 탐색
부모 parentElement 부모 요소만 모두 선택
자식 children 자식 요소만 모두 선택
firstElementChild 첫번째 자식 요소 선택
lastElementChild 마지막 자식 요소 선택
형제 previousElementSibling 이전 형제 요소 선택
nextElementSibling 다음 형제 요소 선택
// HTML 위와 동일 
document.getElementById("btn2").addEventListener("click", function(){
    const test = document.getElementById("test") // 부모
    const li1 = document.getElementById("li1")   // 자식

    // #test의 자식 요소 중 2번 인덱스의 이전 형제요소 클릭 시 작성된 내용 alert로 출력
    console.log(test.children[2])
    console.log(test.children[2].previousSibling)
    test.children[2].previousElementSibling.addEventListener("click", function(){
        alert(this.innerText)
        
        // 이벤트가 발생한 요소의 다음 다음 형제 요소 배경색을 Red로 변경 
        this.nextElementSibling.nextElementSibling.style.backgroundColor = "red"
    })
})

 


요소 생성 및 추가 

1. innerHTML을 이용한 요소 생성 및 추가 

  * innerHTML 원리 

    1) 특정 요소의 내부 내용을 새로운 내용으로 덮어씌움(기존 내용이 사라지는 문제 발생) 

    2) 덮어 씌워지는 새로운 내용을 단순 문자열로 추가하는 것이 아니라, HTML 요소가 포함되어 있으면 

         이를 해석할 수 있도록 HTMLParser를 이용(추가적 해석을 진행하여 속도 느림) 

 

innerHTML 실습

const btn1 = document.getElementById("btn1")
const div1 = document.getElementById("div1")
let count1 = 1; // 반복 횟수를 담을 변수 

btn1.addEventListener("click", function(){

    if(count1 <= 10) {
        const input = "<input type = 'text'>"
        div1.innerHTML += "<div>" + count1 + input + "</div>"
        count1++
    }
})

 

 

document.createElement("태그명")

해당 태그의 요소를 생성하여 반환 = 요소를 생성할 뿐 화면에 출력되지는 않음 

const btn1 = document.getElementById("btn1")
const div1 = document.getElementById("div1")
let count1 = 1; // 반복 횟수를 담을 변수 

btn1.addEventListener("click", function(){
    console.log("??")

    if(count1 <= 10){

        const div = document.createElement("div")
        const input = document.createElement("input")

        // <div id="div1">
        //     <div>
        //         count1
        //         <input type="text">
        //     </div>
        // </div>
        // 위의 형식이 클릭될 때마다 늘어남

        div.innerText = count1
        count1++

        // input을 div의 마지막 자식으로 추가 
        div.append(input)

        // div를 div1의 마지막 자식으로 추가 
        div1.append(div)         
    }
})

 

요소 추가 / 제거하기

- 요소.classList.add("클래스명") : 요소에 클래스 추가 

- 요소.setAttribute("속성명", "속성값") : 요소에 속성 추가, 변경

- 요소.removeAttribute("속성명") : 요소에 속성 제거 

    <h3>요소 추가 / 제거</h3>

        <div class="container">
            <!-- 첫번째 행은 무조건 존재(정적 존재) -->
            <div class="row">
                <input type="text" class="in">
            </div>

            <!-- 두번째 행 이후부터는 삭제 가능         
            <div class="row">
                <input type="text" class="in">
                <span class="remove">&times;</span>
            </div>  
            -->
           
        </div>
    
        <button id="add">추가</button>
        <button id="calc">계산</button>

 

// 추가 버튼 클릭 시 동작 
document.getElementById("add").addEventListener("click", function(){

    // div 생성 및 클래스 부여 
    const div = document.createElement("div")
    div.classList.add("row")

    // input 생성 및 클래스 부여 + type number 지정
    const input = document.createElement("input")
    input.classList.add("in")
    input.setAttribute("type", "number")

    // span 생성 및 클래스 부여 + &times;(x)
    const span  = document.createElement("span")
    span.classList.add("remove") 
    span.innerHTML = "&times;"

    // span에 클릭 이벤트 동작 추가(X버튼 누르면 행 삭제 )
    span.addEventListener("click", function(){

        // 클릭된 X의 부모요소 삭제 
        this.parentElement.remove()
    })


    // 만든 요소들 합치기 
    div.append(input, span)

    // container 클래스에 모두 넣어주기 
    document.querySelector(".container").append(div)

    input.focus

})

// 계산하기 
document.getElementById("calc").addEventListener("click", function(){


    const inputList = document.getElementsByClassName("in")

    let sum = 0; 

    for(let input of inputList) {
        sum += Number(input.value)
    }

    alert("합계: " + sum)

})

'JS > JavaScript' 카테고리의 다른 글

13. 최신 자바스크립트 기술: ES6 문법  (0) 2023.03.04
12. 함수  (0) 2023.03.04
10. JavaScript 객체, JSON  (0) 2023.03.03
9. 윈도우 내장 객체  (0) 2023.03.02
8. 배열  (0) 2023.03.01