JS 자바스크립트 DOM 2 입니다. DOM 첫 게시물은 이전글에서 볼 수 있습니다.
DOM 조작 (nodevalue,nodeName, nodeType)
(className,classList,id,.hasAttribute.getAttribute.setAttribute.removeAttribute,textContent,innerText,innerHTML)
(createElement,createTextNode,appendChild,removeChild,insertAdjacentHTML)
요소의 텍스트는 텍스트에 저장되어 있다.
텍스트 노드에 접근 과 수정 방법은 아래와 같다.
1. 해당 텍스트 노드의 부모 요소 노드를 선택한다.
const one = document.getElementById('one');
console.dir(one); // HTMLLIElement: li#one.red
// nodeName, nodeType을 통해 노드의 정보를 취득할 수 있다.
console.log(one.nodeName); // LI
console.log(one.nodeType); // 1: Element node
2. firstChild 프로퍼티를 사용하여 텍스트 노드를 탐색한다.
const textNode = one.firstChild;
// nodeName, nodeType을 통해 노드의 정보를 취득할 수 있다.
console.log(textNode.nodeName); // #text
console.log(textNode.nodeType); // 3: Text node
3. nodeValue 프로퍼티를 사용하여 노드의 값을 취득한다.
console.log(textNode.nodeValue); // Seoul
4. nodeValue 프로퍼티를 이용하여 텍스트를 수정한다.
textNode.nodeValue = 'Pusan';
nodevalue
nodeName, nodeType을 통해 노드의 정보를 취득할 수 있다.
값말고 노드의 타입과 노드의 종류 를 알수 있다.
className
const elems = document.querySelectorAll('li');
[...elems].forEach(elem => {
// class 어트리뷰트 값을 취득하여 확인
if (elem.className === 'red') {
// class 어트리뷰트 값을 변경한다.
elem.className = 'blue';
}
});
어트리뷰 값을 바로 변경이 가능하다 .
classList
[...elems].forEach(elem => {
// class 어트리뷰트 값 확인
if (elem.classList.contains('blue')) {
// class 어트리뷰트 값 변경한다.
elem.classList.replace('blue', 'red');
}
});
메소드를 이용하여 확인하고 변경을 한다. (contains, replace)
id
.hasAttribute(attribute)
지정한 어트리뷰트를 가지고 있는지 검사한다.
Return : Boolean
.getAttribute(attribute)
어트리뷰트의 값을 취득한다.
Return : 문자열
.setAttribute(attribute, value)
어트리뷰트와 어트리뷰트 값을 설정한다.
Return : undefined
.removeAttribute(attribute)
지정한 어트리뷰트를 제거한다.
Return : undefined
마크업이 포함된 콘텐츠를 추가하는 행위는 크로스 스크립팅 공격(XSS: Cross-Site Scripting Attacks)에 취약하므로 주의가 필요하다.
마크업이란 ?
마크업 언어는 "마크(Mark)"로 둘러싸인 언어이다. "태그(Tag)"로 둘러싸였다고도 표현한다.
출처: https://blog.cordelia273.space/15 [세상의 모든 지식]
출처: https://blog.cordelia273.space/15 [세상의 모든 지식]
textContent
요소의 텍스트 콘텐츠를 취득 또는 변경한다. 이때 마크업은 무시된다.
textContent를 통해 요소에 새로운 텍스트를 할당하면 텍스트를 변경할 수 있다.
이때 마크업을 포함시키면 문자열로 인식되어 그대로 출력된다.
// 요소의 마크업이 포함된 콘텐츠로 변경하면.
one.textContent = '<h1>Heading</h1>';
// 마크업이 문자열로 표시된다.
console.log(one.textContent); // <h1>Heading</h1>
작은 따옴표를 활용하여 요소를 추가한다. 추가할때 마크업은 안적어도 된다.
innerText
innerText 프로퍼티를 사용하여도 요소의 텍스트 콘텐츠에만 접근할 수 있다. 하지만 아래의 이유로 사용하지 않는 것이 좋다.
innerHTML
해당 요소의 모든 자식 요소를 포함하는 모든 콘텐츠를 하나의 문자열로 취득할 수 있다.
이 문자열은 마크업을 포함한다.
const one = document.getElementById('one');
// 마크업이 포함된 콘텐츠 취득
console.log(one.innerHTML); // Seoul
// 마크업이 포함된 콘텐츠 변경
one.innerHTML += '<em class="blue">, Korea</em>';
// 마크업이 포함된 콘텐츠 취득
console.log(one.innerHTML); // Seoul <em class="blue">, Korea</em>
위와 같이 마크업이 포함된 콘텐츠를 추가하는 것은 크로스 스크립팅 공격(XSS: Cross-Site Scripting Attacks)에 취약하다.
크로스 스크립팅 공격은 다음에 알아보도록한다.
innerHTML 프로퍼티를 사용하지 않고 새로운 콘텐츠를 추가할 수 있는 방법은 DOM을 직접 조작하는 것이다. 한 개의 요소를 추가하는 경우 사용한다.
이 방법은 다음의 수순에 따라 진행한다.
createElement(tagName)
태그이름을 인자로 전달하여 요소를 생성한다.
Return: HTMLElement를 상속받은 객체
createTextNode(text)
텍스트를 인자로 전달하여 텍스트 노드를 생성한다.
Return: Text 객체
appendChild(Node)
인자로 전달한 노드를 마지막 자식 요소로 DOM 트리에 추가한다.
Return: 추가한 노드
removeChild(Node)
인자로 전달한 노드를 DOM 트리에 제거한다.
Return: 추가한 노드
insertAdjacentHTML(position, string)
인자로 전달한 텍스트를 HTML로 파싱하고 그 결과로 생성된 노드를 DOM 트리의 지정된 위치에 삽입한다. 첫번째 인자는 삽입 위치, 두번째 인자는 삽입할 요소를 표현한 문자열이다. 첫번째 인자로 올 수 있는 값은 아래와 같다.
순서
--beforebegin --
<p>
-- afterbegin--
내용
--beforeend--
</p>
--afterend--
장점
장점
특정 노드 한 개(노드, 텍스트, 데이터 등)를 DOM에 추가할 때 적합하다
단점
innerHTML보다 느리고 더 많은 코드가 필요하다.
장점
간편하게 문자열로 정의된 여러 요소를 DOM에 추가할 수 있다.
삽입되는 위치를 선정할 수 있다.
단점
XSS공격에 취약점이 있기 때문에 사용자로 부터 입력받은 콘텐츠(untrusted data: 댓글, 사용자 이름 등)를 추가할 때 주의하여야 한다.
innerHTML과 insertAdjacentHTML()은 크로스 스크립팅 공격(XSS: Cross-Site Scripting Attacks)에 취약하다.텍스트를 추가 또는 변경시에는 textContent, 새로운 요소의 추가 또는 삭제시에는 DOM 조작 방식을 사용하도록 한다.