-
DOM - 요소노드에 대한 접근프론트엔드/DOM 2020. 10. 7. 01:32
'DOM'은 'HTML' 문서의 요소와 내용들을 객체화시킨 것이다.
그리고 이러한 객체에 접근하여 컨트롤을 해줄 수 있다.
그리고 이때 접근하기 쉽게 메서드와 프로퍼티가 제공된다.
여기서는 문서의 요소(Element) 노드에 어떻게하면 접근할 수 있는지를 알아본다.
단일 요소에 접근하기
1. getElementById()
대략 해석해서 쓰자면 다음과 같다.
'파라미터로 주어진 문자열과 동일한 id값를 통해 요소를 얻을 수 있게 한다.'
'getElementById()'에 제공한 문자열과 동일한 'id' 속성을 가진 요소를 HTML 문서에서 찾아준다.
그리고 이 'id' 속성을 가진 'Element' 객체를 반환한다.
즉 해당 요소를 이용할 수 있게 도와준다는 말이다.
<body> <p id="test"> ID테스트입니다. </p> <script> document.getElementById('test').innerHTML = "아이디 속성으로 접근합니다."; // 해당 코드를 실행하면 // 'test'를 'id'로 가진 <p> 태그의 내용이 // "아이디 속성으로 접근합니다"로 변경된다. </script> </body>
코드는 위와 같다.
위와 같이 메서드를 안에 문자열을 넣어주면 해당 문자열과 동일한 'id'값을 가진 요소의 객체를 반환한다.
<body> <p id="test"> ID테스트입니다. </p> <p id="test"> ID테스트입니다.2 </p> <script> document.getElementById('test').innerHTML = "아이디 속성으로 접근합니다."; // 해당 코드를 실행하면 // 첫번째 'test'를 'id'로 가진 <p> 태그의 내용이 // "아이디 속성으로 접근합니다"로 변경된다. </script> </body>
참고로 해당 메서드는 'html' 문서 내에서 단 하나만 존재해야하는 'id'값에 접근하는 것이다.
그래서 메서드의 이름도 자세히 보면 다른 요소 객체 반환 메서드와 달리 'getElement'다.
즉 여러개가 아닌 하나의 요소만 얻게해준다는 것이다.
그리고 위 코드처럼 같은 'id'값을 두개를 써도 둘 중 처음 나오는 'id'값의 요소 객체만을 반환한다.
복수 요소에 접근하기
복수 요소에 접근하는 대략 세가지 메서드가 존재한다.
● getElementsByTagName
● getElementsByClassName
● querySelectorAll
세 가지 메서드 모두 단일 요소를 선택하는 'getElementById'와 다르다.
메서드 이름에 'All'이나 'Elements'와 같이 복수 요소를 선택할 수 있다는 뜻의 단어를 내포하고 있다.
즉 세가지 메서드를 이용하면 'HTML' 문서에서 내가 원하는 모든 요소의 객체를 반환해준다는 것이다.
앞서 'getElementById'는 동일 'id' 값이 아무리 많아도 그중 첫 번째 요소만 반환했다.
하지만 위의 세 가지 메서드는 메서드의 조건에 해당하는 모든 요소의 객체를 반환한다.
각 메서드 별로 살펴보자.
1. getElementsByTagName()
대략 해석해서 쓰자면 다음과 같다.
'파라미터로 주어진 태그명과 같은 복수의 태그 요소들의 객체를 반환한다.'
즉 'getElementsByTagName'를 쓰면 같은 태그 네임을 가진 복수의 요소의 객체를 반환한다는 것.
코드로 보자.
<body> <p> 일반 문장입니다. </p> <p> 일반 문장입니다. </p> <p> 일반 문장입니다. </p> <script> document.getElementsByTagName('p').innerHTML = "태그네임으로 접근합니다"; </script> </body>
위 코드를 실행하면 어떻게 될까? 결론부터 말하면 아무런 변화가 없다.
얼핏보면 <P> 태그를 가진 모든 요소의 내용이 "태그네임으로 접근합니다"로 바뀔 것 같다.
하지만 그렇지 않다.
'getElementsByTagName'는 문서 내에 있는 조건에 맞는 요소의 객체를 모두 반환한다고 했다.
하지만 요소의 객체를 모두 반환한다고해서 모든 <p> 태그의 내용을 바꿔버린다면 문제가 생길 것이다.
만약 세 개의 <p> 태그 중 마지막 <p> 태그만 바꾸고 싶다면 이 메서드를 사용할 수 없기 때문이다.
그래서 'getElementsByTagName' 뿐 아니라 다른 복수 요소에 접근하는 모든 메서드는
조건에 맞는 객체를 유사 배열이라는 객체라는 배열과 유사한 형태로 만들어 객체를 반환한다.
우선 위 코드에서 쓴 'document.getElementsByTagName('p')' 를 'console.log'로 출력해보자.
<body> <p> 일반 문장입니다. </p> <p> 일반 문장입니다. </p> <p> 일반 문장입니다. </p> <script> console.log(document.getElementsByTagName('p')); </script> </body>
위 코드를 실행한 결과는 아래와 같다.
어딘지 우리가 알고있는 배열과 비슷하다. 실제로 사용법도 동일하다.
<body> <p> 일반 문장입니다 1. </p> <p> 일반 문장입니다 2. </p> <p> 일반 문장입니다 3. </p> <script> document.getElementsByTagName('p')[0].innerHTML = "유사배열 1" document.getElementsByTagName('p')[1].innerHTML = "유사배열 2" document.getElementsByTagName('p')[2].innerHTML = "유사배열 3" // 메서드 뒤에 배열처럼 []로 인덱스를 선택해줬다. // 이 상태로 코드를 실행하면 // <p> 태그들은 각각 // "유사배열 1", "유사배열 2", "유사배열 3"으로 바뀐다. </script> </body>
만약 복수의 요소 중 한 개만 선택해서 사용하고 싶다면 위의 코드처럼 하면된다.
배열 쓰듯이 인덱스 넘버를 지정해주면 거기에 맞는 요소를 컨트롤 할 수 있다.
만약 복수로 <p> 태그의 한번에 컨트롤 하고 싶다면 다음과 같이 하면 된다.
<body> <p> 일반 문장입니다 1. </p> <p> 일반 문장입니다 2. </p> <p> 일반 문장입니다 3. </p> <script> for(i=0; i < document.getElementsByTagName('p').length; i++){ document.getElementsByTagName('p')[i].innerHTML = "유사배열 "+(i+1); } // for 문을 이용하면 인덱스의 값을 자동으로 바꾸면서 // 해당 HTML에서 원하는 모든 요소를 한번에 컨트롤 할 수 있다. // 참고로 해당 코드를 실행하면 다음과 같다. // 각각의 <p> 태그 내용은 // "유사배열 1", "유사배열 2", "유사배열 3"로 바뀐다. </script> </body>
for문을 이용해서 인덱스를 자동으로 지정하면 HTML 문서 내에서 해당 조건에 맞는 모든 요소를 컨트롤할 수 있다.
하지만 뭔가 복잡하다. 더 쉬운 방법도 존재한다.
하지만 지금은 아니고 추후 유사배열로 다시 정리할 예정이다.
우선 여기선 남은 두 메서드를 살펴보자.
2. getElementsByClassName()
대략 풀어쓰면 이렇다.
'파라미터로 주어진 문장과 일치하는 클래스 네임을 가진 복수 요소들의 객체를 반환한다.'
즉 'getElementsByClassName'는 원하는 조건에 맞는 클래스 속성을 가진 요소의 객체를 컨트롤 할수 있게 한다.
그리고 당연하게도 복수 요소에 접근하는 메서드라
'getElementsByTagName'과 같이 유사배열의 형태로 객체를 반환한다.
<body> <p class = "t_class"> 클래스적용 문장입니다 1. </p> <p class = "t_class"> 클래스적용 문장입니다 2. </p> <p class = "t_class"> 클래스적용 문장입니다 3. </p> <script> document.getElementsByClassName('t_class')[0].innerHTML = "클래스로 접근합니다 1"; document.getElementsByClassName('t_class')[1].innerHTML = "클래스로 접근합니다 2"; document.getElementsByClassName('t_class')[2].innerHTML = "클래스로 접근합니다 3"; // 해당 내용을 실행하면 다음과 같다 // <p> 태그의 내용은 순서대로 이렇게 바뀐다. // "클래스로 접근합니다 1" // "클래스로 접근합니다 2" // "클래스로 접근합니다 3" </script> </body>
사용법도 'getElementsByTagName'과 같다.
복수의 요소를 한번에 컨트롤 하는 것도 동일하다.
<body> <p class = "t_class"> 클래스적용 문장입니다 1. </p> <p class = "t_class"> 클래스적용 문장입니다 2. </p> <p class = "t_class"> 클래스적용 문장입니다 3. </p> <script> for(i=0; i < document.getElementsByClassName('t_class').length; i++){ document.getElementsByClassName('t_class')[i].innerHTML = "클래스로 접근합니다"; } // 해당 코드 실행시 // <p> 태그의 내용은 모두 "클래스로 접근합니다"로 변경 </script> </body>
이 또한 더 편하게 복수의 요소를 컨트롤할 수 있는 방법이 있지만 우선은 넘어간다.
3. querySelectorAll()
대략 해석하면 다음과 같다.
'파라미터를 통해 주어진 선택자를 이용해 조건에 맞는 복수 요소들의 객체를 반환한다.'
앞서 말한 메서드들은 'tagname', 'class', 'id' 와 같이 'HTML'에서 제공하는 기능을 가지고
반환반을 요소들을 선택할 수 있었다.
하지만 'querySelectorAll()'를 쓰면 CSS 선택자를 이용하여 요소들을 선택할 수 있다.
이 방법을 이용하면 'id', 'class' 처럼 일일이 속성을 지정하지 않아도 요소들을 구분하여 선택이 가능하다.
'tagname'의 경우 'HTML'에서 조건에 해당하는 모든 요소들의 객체를 반환하기에 부담스럽다.
하지만 'querySelectorAll'는 조금 더 세밀한 조건 설정을 통해 원하는 객체 반환이 비교적 쉽다.
우선 코드를 보자.
<body> <ul> <li> 일번 </li> <li> 이번 </li> </ul> <div> <li> 일번 </li> <li> 이번 </li> </div> <script> document.querySelectorAll('li')[0].innerHTML = " ul > li 쿼리셀렉터로 접근합니다"; document.querySelectorAll('li')[1].innerHTML = " ul > li 쿼리셀렉터로 접근합니다"; document.querySelectorAll('li')[2].innerHTML = " div > li 쿼리셀렉터로 접근합니다"; document.querySelectorAll('li')[3].innerHTML = " div > li 쿼리셀렉터로 접근합니다"; // 모든 <li> 태그 내의 내용은 순서대로 아래처럼 바뀐다. // " ul > li 쿼리셀렉터로 접근합니다"; // " ul > li 쿼리셀렉터로 접근합니다"; // " div > li 쿼리셀렉터로 접근합니다"; // " div > li 쿼리셀렉터로 접근합니다"; </script> </body>
위 코드는 우선 문서 내의 모든 <li> 태그의 객체를 반환받아 컨트롤하는 코드다.
'tagname' 선택과 비슷한 모양새다.
하지만 이럴 때보다 아래 코드의 경우 'querySelectorAll'의 진가가 드러난다.
<body> <ul> <li> 일번 </li> <li> 이번 </li> </ul> <div> <li> 일번 </li> <li> 이번 </li> </div> <script> document.querySelectorAll('ul > li')[0].innerHTML = " ul > li 쿼리셀렉터로 접근합니다"; document.querySelectorAll('div > li')[0].innerHTML = " div > li 쿼리셀렉터로 접근합니다"; // 위 코드를 실행하면 <li> 태그는 순서대로 이렇게 바뀐다. // "ul > li 쿼리셀렉터로 접근합니다" // "이번" // "div > li 쿼리셀렉터로 접근합니다" // "이번" </script> </body>
전의 코드처럼 투박하게 <li> 태그를 전부 선택한 것이 아니라 CSS 선택자 방식을 이용했다.
각각 <div>, <ul>의 아래 있는 <li> 태그를 구분하여 선택했다.
당연히 유사배열을 통해 돌려받는 인덱스도 달라진다.
그리고 당연히 'querySelectorAll' 메서드도 조건에 맞는 모든 요소를 선택하고 싶다면 for 문을 쓴다.
'프론트엔드 > DOM' 카테고리의 다른 글
DOM 조작 - 속성 노드의 생성, 수정, 삭제 2 (0) 2020.10.16 DOM 조작 - 속성 노드의 생성, 삭제 (0) 2020.10.16 DOM 조작 - 텍스트 노드에 대한 접근 / 수정 (0) 2020.10.13 DOM - 노드의 관계를 통한 접근 (0) 2020.10.07 DOM에 관해서 (0) 2020.10.07