Hoon222y

[JavaScript] 10장. 문서 객체 모델 본문

코딩/교육

[JavaScript] 10장. 문서 객체 모델

hoon222y 2019. 1. 10. 20:06

문서 객체 모델(DOM)


10.1 문서 객체 모델과 관련된 용어 정리

문서 객체 모델

- 넓은 의미로 웹 브라우저가 HTML을 인식하는 방법

- 좁은 의미로 document 객체와 관련된 객체의 집합

- HTML 페이지에 태그를 추가, 수정, 제거할수 있음


태그 : HTML 페이지에 존재하는 html이나 body 를 태그라고 한다. 

문서 객체 : 태그를 자바스크립트에서 이용할 수 있는 객체로 만든것. 

요소 노드 : HTML 태그

텍스트 노드 : 요소 노드 안에 들어 있는 글자


10.2 문서 객체 만들기(1) - 텍스트 노드를 갖는 문서 객체 생성

 createElement(tagName)

  요소 노드를 생성한다. 

 createTextNode(text)

  텍스트 노드를 생성한다. 

 appendChild(node) 

  객체에 노드를 연결한다. 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!DOCTYPE html>
<html>
<head>
    <script>
        window.onload = function () {
            var header = document.createElement('h1');
            var textNode = document.createTextNode('Hello DOM');
            // 노드를 연결합니다.
            header.appendChild(textNode);
            document.body.appendChild(header);
        };
    </script>
</head>
<body>
</body>
</html>
cs

 이런식으로 appendChild로 노드들을 연결해준다. 하지만 

1
2
3
4
5
6
7
8
9
10
11
12
<head>
    <script>
        window.onload = function () {
            // 변수를 선언합니다.
            var header = document.createElement('h1');
            //var textNode = document.createTextNode('Hello DOM');
            //header.appendChild(textNode);
            header.innerHTML= 'Hello innerHTML'
            document.body.appendChild(header);
        };
    </script>
</head>
cs

 이러한 방식으로도 같은 구현이 가능하기 때문에 보통은 createTextNode를 사용하지 않는다.  


10.3 문서 객체 만들기(2) - 텍스트 노드를 갖지 않는 노드

- 대표적으로 img 가 있다. 텍스트 노드가 없는 대신에 많은 속성들이 존재한다. 

 setAttribute(name, value) 

 객체의 속성을 지정한다.

 getAttribute(name)

 객체의 속성을 가져온다. 


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<!DOCTYPE html>
<html>
<head>
    <script>
        window.onload = function () {
            var img = document.createElement('img');
            img.src = 'Penguins.jpg';
            img.width = 500;
            img.height = 350;
            document.body.appendChild(img);  // 노드를 연결
        };
    </script>
</head>
<body>
</body>
</html>
cs

 이런식으로 이미지를 불러올 수 있다. 하지만 이 경우에 눈여겨볼점은 scr, width 등을 동적으로 얼마든지 속성을 추가하거나 제거가 가능하다는 점이다. 

1
2
3
4
5
6
7
8
9
10
11
12
13
<head>
    <script>
        window.onload = function () {
            var img = document.createElement('img');
            img.src = 'Penguins.jpg';         // 상대경로 uri
            img.src = '../images/img.jpg';    // 절대경로 uri
            img.width = 500;
            img.height = 350;
            img.gender = 'female';
            document.body.appendChild(img);
        };
    </script>
</head>
cs

 해당 코드를 실행하고 돌려보면 img.gender 부분은 사라지는것을 볼 수 있다. 이유는 표준에 정의된 속성이 아니기 때문이다. 따라서 아래와 같이 해야한다. 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<head>
    <script>
        window.onload = function () {
            // 변수를 선언합니다.
            var img = document.createElement('img');
            img.setAttribute('src''Penguins.jpg');
            img.setAttribute('width'500);
            img.setAttribute('height'350);
            // setAttibute() 메서드를 사용하지 않으면 불가능합니다.
            img.setAttribute('data-property'350);
            // 노드를 연결합니다.
            document.body.appendChild(img);
        };
    </script>
</head>
cs

 해당 코드를 보면서 이야기 해보자. 이 때 임의로 넣는 속성의 경우 앞에 'data-' 를 붙여서 속성의 이름을 정해야 한다. 

 만약에 img.data-gender = 'female'; 에 대해서 작동이 안되는 이유에 대해서 생각해본다면 객체의 속성명은 -를 쓰지 못하고 _,$만 사용할 수 있기 때문에 작동을 하지 않는것이다. 이를 해결하기 위해서는 img.['data-gender'] = 'female'; 이라고 하면 사용이 가능하다. 이는 선언방법은 지키지 않지만 사용하겠다는 의미이다. 하지만 이 경우에도 개발자 모드로 확인하면 data-gender 부분이 나타나지 않게된다. 


10.4 문서 객체 만들기(3) - innerHTML을 이용한 객체 만들기

- 문서 객체의 innerHTML 속성은 태그의 내부를 의미하는 속성이다. 

- 단순하게 텍스트 뿐만 아니라 자식 태그도 넣을 수 있다.  

- 신뢰할 수 없는 경우에는 innerText 를 사용해야 한다.(HTML은 전부 대문자 Text는 T만 대문자.)


10.5 문서 객체 가져오기(1) 

- getElementById(id) : 태그의 id 속성이 id 매개변수와 일치하는 문서 객체를 가져온다. 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<!DOCTYPE html>
<html>
<head>
    <script>
        window.onload = function () {
            // 문서 객체를 가져옵니다.
            var header1 = document.getElementById('header-1');
            var header2 = document.getElementById('header-2');
            // 문서 객체의 속성을 변경합니다.
            header1.innerHTML = 'with getElementById()';
            header2.innerHTML = 'with getElementById()';
        };
    </script>
</head>
<body>
    <h1 id="header-1">Header</h1>
    <h1 id="header-2">Header</h1>
</body>
</html>
cs

 해당 코드를 보면 header1,2 에 각각의 매개변수에 해당하는 객체들을 저장하고, 그 안에 있는 innerHTML을 바꾸는 동작이다. 이 때는 출력이 'with getElementById' 라는 값이 2번 적히게 된다.  

 그렇다면 같은 id값이 많은 경우에는 어떻게 될까? 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<!DOCTYPE html>
<html>
<head>
    <script>
        window.onload = function () {
            // 문서 객체를 가져옵니다.
            var header = document.getElementById('header');
            header.innerHTML = 'with getElementById()';
        };
    </script>
</head>
<body>
    <h1 id="header">Header</h1>//with getElementById()
    <h1 id="header">Header</h1>//header
    <h1 id="header">Header</h1>//header
</body>
</html>
cs

 이 경우에는 13~15 주석에서 알 수 있듯 첫 번째만 변하게 된다. id 속성값은 고유해야 하므로 속성값을 찾으면 더 이상 찾지 않음으로 처음에만 호출이 되는것이다. 


10.6 문서 객체 가져오기(2)

 getElementsByName(name) 

 태그의 name 속성이 name 매개변수와 일치하는 문서 객체를 배열로 가져온다.  

 getElementsByTagName(tagname)

 tagName 매개변수와 일치하는 문서 객체를 배열로 가져온다. 

 getElemendById 와 getElementsByName에서 후자는 뒤에 s 가 붙는것을 주의해야 한다. 한번에 여러개의 문서 객체를 가져올 수 있기 때문에 복수형으로 표현한다. 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<!DOCTYPE html>
<html>
<head>
    <title>Index</title>
    <script>
        window.onload = function () {
            // 문서 객체를 가져옵니다.
            var headers = document.getElementsByTagName('h1');
           
            alert(Array.isArray(headers));
            //진짜 배열인지 물어봤는데 false 가 나온다. 유사 배열객체 이다. 
            //따라서 진짜 배열이 아니기 떄문에 for in 반복문을 사용하면 안된다. 
            /*
            for(var key in headers){
                alert(key);
            }         // 이렇게 하면 5번 반복된다. 따라서 그냥 for문을써야함
            */
            for(var i=0;i<headers.length;i++){
                headers[i].innerHTML = 'with getElementsByTagName()';
            }
            /*
            headers[0].innerHTML = 'with getElementsByTagName()';
            headers[1].innerHTML = 'with getElementsByTagName()';
            //[0][1] 이런식으로 하면 안됨 배열의 크기인 만큼
            */
        
        };
    </script>
</head>
<body>
    <h1>Header</h1>// with getElementsByTagName() 출력
    <h1>Header</h1>// with getElementsByTagName() 출력
</body>
</html>

cs

//

 해당 코드를 살펴보자. headers는 배열이므로 반복문을 사용할 수 있다. 하지만 for in 반복문은 사용할 수 없다. 왜냐하면 문서 객체 이외의 속성에도 접근하기 때문이다 ( 해당 소스에서 for in 문을 돌 때 5번 실행되는것을 통해 확인 가능)


10.7 문서 객체 가져오기(3)

 querySelector(선택자) 

 선택자로 가장 처음 선택되는 문서 객체를 가져온다. 

 querySelectorAll(선택자)

 선택자를 통해 선택되는 문서 객체를 배열로 가져온다. 

1
2
3
4
5
6
7
8
9
10
11
12
13
<head>
    <title>DOM Basic</title>
    <script>
        window.onload = function () {
            var header1 = document.querySelector('#header-1');
            //#은 css 선택자인데 #은 id 를 말한다. 
            var header2 = document.querySelector('#header-2');
 
            header1.innerHTML = 'with getElementById()';
            header2.innerHTML = 'with getElementById()';
        };
    </script>
</head>
cs

가 가장 기본적인 활용이다 . 만약 querySelector을 사용할 경우에는 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<head>
    <title>DOM Basic</title>
    <script>
        window.onload = function () {
            var header = document.querySelector('h1');
            // 문서 객체의 속성을 변경합니다.
            header.innerHTML = 'with getElementById()';
            header.innerHTML = 'with getElementById()';
        };
    </script>
</head>
<body>
    <h1>Header</h1>    //with getElementById()
    <h1>Header</h1>    //header
</body>
cs

 주석과 같이 가장 처음에 선언된 h1 문서 객체에만 적용이 된다. 하지만 querySelectorAll을 사용하게 되면 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<!DOCTYPE html>
<html>
<head>
    <title>DOM Basic</title>
    <script>
        window.onload = function () {
            var headers = document.querySelectorAll('h1');
            // 문서 객체의 속성을 변경합니다.
            for(var i=0;i<headers.length;i++){
                headers[i].innerHTML = 'with getElementById()';
            }
 
        };
    </script>
</head>
<body>
    <h1 >Header</h1>
    <h1>Header</h1>
</body>
</html>
cs

 과 같이 for 반복문을 통해서 선택되는 모든 문서 객체의 값을 바꿔줄 수 있다. 


10.8 문서 객체의 스타일 조작

- <style> 태그를 이용하면 문서 객체의 스타일을 변경할 수 있다. 

1
2
3
4
5
6
7
8
9
10
<script>
    window.onload = function(){
        var header = document.querySelector('h1');
        header.style.color = 'yellow';
        //header.style.background-color = 'blue';  이렇게 하면 안됨. 
        // header.style['background-color'] = 'blue'; 이렇게 하거나
        header.style.backgroundColor = 'blue';     
        //이것 처럼 하이픈을 빼고 뒤에꺼 대문자로 바꿔도 된다. 
    }// 동적으로 스타일 넣어준 예제 
</script>
cs

 이렇게 태그의 스타일을 변경할 수 있다. 이때 주의 할 점이 두가지가 있다. 

1. 자바스크립트는 -를 식별자에 사용할 수 없으므로 -를 없애고, 뒤에 오는 문자를 대문자로 표현한다. 

2. 문자열로 스타일 속성에 접근할 때는 

 header.style.['backgroundColor'] 혹은 header.style.['background-color'] 둘 다 가능하다. 



[과제]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<!DOCTYPE html>
<html>
<head>
    <title>DOM Basic</title>
    <script>
 
    window.onload = function(){
        var header = document.querySelector('h1');
        var color = document.querySelector('#color');
        var backgroundColor = document.querySelector('#background-color');
        var btn1 = document.querySelector('#btn1');
        var btn2 = document.querySelector('#btn2');
 
        btn1.onclick = function(){
            header.style.color = color.value;
            header.style.backgroundColor = backgroundColor.value;     
        }
        
        btn2.onclick = function(){
            header.style.color = 'black';
            header.style.backgroundColor = 'white';     
            backgroundColor.value = '#ffffff';
            color.value = '#000000';
        }
    } 
    </script>
</head>
<body>
    <h1>Dynamic style example</h1>
    <hr />
    
     배경색<input type='color' value = '#ffffff' id= 'background-color'/>
     글꼴색<input type='color' value = '#000000' id = 'color'/>
    <button id = 'btn1'>적용</button>
    <button id = 'btn2'>초기화</button>
    
    <!-- 사용자가 선택했을 때 h1 테그에 적용되도록 바꾸어 보아라
    초기화 버튼을 누르면 input 도 초기화 되게 해보아라-->
    
</body>
</html>
cs


10.9 문서 객체 제거

- removeChild(child) : 문서 객체의 자식 노드를 제거한다. 즉, 삭제할 부모가 호출해야 한다. 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!DOCTYPE html>
<html>
<head>
    <title>DOM Basic</title>
    <script>
        window.onload = function () {
            // 문서 객체를 가져옵니다.
            var willRemove = document.getElementById('will-remove');
            // 문서 객체를 제거합니다.
            document.body.removeChild(willRemove);
        };
    </script>
</head>
<body>
    <h1 id="will-remove">Header1</h1>
    <h1>Header2</h1>
</body>
</html>
cs

 의 결과값은 header2만 출력된다. 


[지우는 2가지 방법]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<!DOCTYPE html>
<html>
<head>
    <title>DOM Basic</title>
    <script>
        window.onload = function () {
               // 문제 만약에 div안에 저 h1 두개 넣었을떄 저 안에 있는거 중애서 
               // 위에 꺼만 삭제할 수 있는 방법은? 즉, 바디의 자식이 아니라 div 의자식일때는 
               // 어떻게 지울 수 있을까? 
            // 문서 객체를 가져옵니다.
            var willRemove = document.querySelector('#will-remove');
            var parent = document.querySelector('div');
 
            parent.removeChild(willRemove);
        };
        
        
    </script>
</head>
<body>
    <div>
        <h1 id="will-remove">Header</h1>
        <h1>Header</h1>
       </div>
</body>
</html>
cs

 과

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<!DOCTYPE html>
<html>
<head>
    <title>DOM Basic</title>
    <script>
        window.onload = function () {
            // 문서 객체를 가져옵니다.
            var willRemove = document.querySelector('#will-remove');
            //var parent = document.querySelector('div');
            //parent.removeChild(willRemove);
            //별도로 부모를 찾지 않더라도 삭제할 노드르ㄹ 기준으로 parent 노드를 읽고
            //재귀적으로 제거
            willRemove.parentNode.removeChild(willRemove);
        };
    </script>
</head>
<body>
    <div>
        <h1 id="will-remove">Header</h1>
        <h1>Header</h1>
       </div>    
</body>
</html>
cs

 가 있다. 이 경우는 h1 태그에서 부모 노드로 이동하고 부모 노드에서 자식 노드를 삭제한것이다. 

 willRemove.parentNode.removeChild(willRemove); 기억하자. 여기서 willRemove는 변수명이므로 상황에 따라 달라진다


[과제]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<!DOCTYPE html>
<html>
<head>
    <title>DOM Basic</title>
    <style>
    img {
        float : left;
    }
    </style>
    <script>
    window.onload = function(){
            setIntervalfunction(){
                var firstImg = document.querySelector('img');
                firstImg.parentNode.appendChild(firstImg);
            },1000);
    }
    </script>
</head>
<body>
    <h1>Rotation Images</h1>
    <hr/>
    <div id = 'images'>
        <img src = '../images/Chrysanthemum.jpg' width='150' />
        <img src = '../images/Desert.jpg' width='150' />
        <img src = '../images/Hydrangeas.jpg' width='150' />
        <img src = '../images/Jellyfish.jpg' width='150' />
        <img src = '../images/Lighthouse.jpg' width='150' />
    </div>
    <!-- 계속 회전하게 만들어보아라  -->
 
</body>
</html>
cs


'코딩 > 교육' 카테고리의 다른 글

[JavaScript] 2장. 기본 문법  (0) 2019.01.10
[JavaScript] 11장. 이벤트  (0) 2019.01.10
[JavaScript] 9장. 브라우저 객체 모델  (0) 2019.01.10
[JavaScript] 5장. 함수  (1) 2019.01.09
[0109] 함수  (1) 2019.01.09
Comments