Computer Science/웹 프로그래밍

DOM의 요소 관계와 JS에서의 사용

mitdog 2024. 7. 9. 10:16

DOM이 무엇인지는 다음을 참고하시고 : HTML에서의 DOM 구조

요소 관계

중요한 것은 DOM이 hierachical(계층적)이라는 것이다.

계층적임의 예시는 다음을 보자.

<p id="foo">This is a paragraph of text with a
<a href="/path/to/another/page.html">link</a>.</p>

를 DOM 구조를 나타내면,


자식들은 순서대로 first, second... 가 되고
자식들의 부모는 parentNode로 접근이 가능하며
자식들 끼리는 nextSilbing, previousSibling으로 접근이 가능하다.

요소 접근하기

document.getElementById(id)

html페이지에서 유일한 id를 찾아서 그것의 DOM을 반환한다.

!주의! : getElement"S"임에 주의!! id는 유일해서 Element이지만 얘네는 여러개 가능해서 복수형임!!

document.getElementsByTagName(name)

html페이지에서 특정 이름의 태그(img, a, p..)를 가진 것들을 반환한다.

계층적임에 주의하라

id는 유일하니까 크게 상관이 없지만. tag는 다르다.

<form name="myform">
    <input type="text" id="target" name="text1">

여기서 text1을 얻고 싶다고 해보자.
var obj = document.myform.text1 로 얻을 수 있다. (혹은 document.myform["text1"])


왜 document.text1은 안될까?
이유는 계층적이라서다. document가 인지하는 자식은 myform인데, text1은 바로 밑 자식이 아니지 않는가?
myform을 타고 들어가야 인지할 수 있는 것이다.
(물론 getElementById하면 바로 구할수 있긴 한데, id가 아니면 이러한 것)

여러개를 반환받음에 주의하라

아까 서술했듯이 element"S"이다. 여러개를 넘겨줄 수 있다는 소리다.
여러개를 어떻게 받는가? 배열 형태로 받는다.

<body>
    <ul>
        <li>List item 1</li>
        ...
        <li>List item 5</li>
    </ul>
    <script>
        var list = document.getElementsByTagName('ul')[0];
        var allItems = list.getElementsByTagName('li');

여기서 저기 li의 "List item.." 이라는 text에 접근하고 싶다고 해보자.
ByTagName('li')를 박으면 안돼? 라는 물음이 생길 수 있다. 안된다.
그러면 문서 전체의 li를 받는 것이기 때문이다. 우리가 원하는건 저 ul안의 li들인데.

ul도 여러개가 있을 수 있기 때문에, 가장 첫 번째 ul임을 알리기 위해 [0]이라는 인덱스를 달아준다.
그리고 거기서 li들을 받는다. 또 각각의 li마다 text에 접근하고 싶으면
allItems[index].firstChild.data(firstChild.data = innerHTML)로 하면 된다.
핵심은 배열로 받았기 때문에 인덱스로 접근한다는 것이다.

 

!주의!
인덱스로 접근하지 않으면, 특정 값을 바꿀 수 없다!!! (텍스트라던가 src의 주소값이라던가) 바꾸려는게 하나여도 [0] 붙여서 무조건 인덱스로!!!!!

document.getElementsByClassName(name)

html페이지에서 특정 이름의 class를 가진 것들을 반환한다.

요소에 접근하여 내용 변경하기

4가지의 메소드가 있다.

element.innerHTML = new html code(or text..)

해당 element의 태그 안의 모든 것을 수정할 수 있다.

<div id="main_div"><div><p>test div</p></div></div>

가 있다고 하자. 여기서
var mainDiv = document.getElementById('main_div') 로 가져왔다.
mainDiv.innerText = " " 해버리면 어떻게 될까?

<div id="main_div"> </div>

말 그대로 해당 element의 여는 태그 닫는 태그 사이 모든 것을 가져오거나 수정할 수 있는 메소드이다.

element.attribute = new value

여기서 attribute는 변수이다. 즉,
element.src = ...
element.style = ..
이런식으로 사용한다는 말이다.
해당 속성(attribute)의 값을 변경할 수 있다.

element.setAttribute(attribute, value)

기능 자체는 위 element.attribute와 똑같다. 중요한 차이점 하나가 있을뿐.
위에 메소드는 그 속성(attribute)가 없었다면 사용이 불가능하다.
(ex. 접근한 element에 style 속성이 없는데 elemenet.src = ... 시도 -> 불가능)
지만 이 setAttribute는 없으면 만들어서 넣는다. 있으면 그걸 변경하는거고.

element.style.property = new style

여기서 property는 css 속성들이다. (ex. color, width, display...)
해당 element의 style에 관여해 변경이 가능하다.

Q. 얘도 style이 없으면? 만들어서 넣는가??
원래 모든 태그는 style이 기본적으로있다. 그래서 만들어서 넣는게 아니라 원래있음.

 

!주의할점 2개! 
1. element.style.property에서 속성 값(property) 형태가 좀 다르다.
(ex. font-family => fontFamily, font-style => fontStyle) 처럼 '-'(하이픈)을 지우고 대문자로 붙인다.

2. 속성 값(new style)은 문자열 이어야 한다. 단위도 있고.
(ex. element.style.width = "200px")

 

요소 추가하거나 삭제하기

얘는 5가지의 메소드가 있다.

1. document.createElement(element)

말 그대로 새로운 element의 DOM을 만드는 것.
보통 만들어서 append로 추가한다!

var newNode = document.createTextNode("추가요");
document.getElementById("부모아이디").appendChild(newNode);

2. document.removeChild(element)

부모 기준 자식을 삭제한다.
사용 형태는

  • 부모.removeChild(대상) (exx. parent.removeChild(...))
  • removeChild(부모.대상) (ex. removeChild(parent.firstChild))
!주의! 
remove시 child.lenght의 크기가 변하는 것에 주의하라!!
 
Example: 어떤 부모의 모든 자식들 지우기

아 자식 다 지워야지 ㅎㅎ

for(i=0;i<child.length;i++)
    parent.removeChild(child[i]);

쉽네 ㅋ
하면 틀린다. 왜? removeChild하면서 동시에 child.length도 감소하니까.
이를 해결하기 위한 방법은 여러가지가 있다.

while(child[0])
    parent.removeChild(child[0]) // or parent.removeChild(parent.firstChild)

child를 굳이 getElement....로 안받아도 할 수 있다.

while(parent.hasChildNodes()) // hasChildNodes() 이용
    parent.removeChild(parent.fisrtChild)

 

3. document.appendChild(element)

부모에다가 element를 추가한다.

  • 부모.appendChild

4. document.replaceChild(new element, old element)

remove와 비슷하나, 대체한다는점이 다르다.

5. document.write(text)

얘는 쓰기가 좀 그런게,
전에 있는 모든 html을 다 지우고, 새로운 html 문서를 만든뒤 그 문서의 body에다가 text를 쓴다.