반응형
DOM 활용 (CRUDA)
DOM의 기초적으로 활용하기 위해서
Create (생성) / Read (읽기) / Update (갱신) / Delete (삭제) / Append (적용)
하는 법을 알아보겠습니다.
생성 (Create)
// createElement
const oneDiv = document.createElement('div'); // oneDiv 변수에 <div> tag를 생성한다.
console.log(oneDiv); // <div></div>
// createTextNode
const textNode = document.createTextNode('Banana');
읽기 (Read)
// querySelector
// 입력한 선택자와 일치하는 문서 내의 첫 번째 요소를 반환한다.
// 일치하는 요소가 없다면 null을 반환한다.
// id, class, tag 전부 가능하다.
const container = document.querySelector('#container'); // id명이 container인 첫 번째 요소 선택
const container = document.querySelector('.container'); // class명이 container인 첫 번째 요소 선택
const container = document.querySelector('container'); // tag명이 container인 첫 번째 요소 선택
// querySelectorAll
// 입력한 선택자와 일치하는 모든 요소를 반환한다.
// id, class, tag 전부 가능하다.
const items = document.querySelectorAll('#item'); // id명이 item인 모든 요소 선택
const items = document.querySelectorAll('.item'); // class명이 item인 모든 요소 선택
const items = document.querySelectorAll('item'); // tag명이 item인 모든 요소 선택
// querySelector 대신 getElementById, getElementsByClassName, getElementsByTagName을 사용할 수 있다.
// getElementById
// 입력한 id명과 일치하는 문서 내의 첫 번째 요소를 반환한다.
// id만 가능하다.
const itemId = document.getElementById('item'); // id명이 item인 첫 번째 요소 선택
// getElementByClassName
// 입력한 class명과 일치하는 문서 내의 첫 번째 요소를 반환한다.
// class만 가능하다.
const itemClass = document.getElementByClassName('item'); // class명이 item인 첫 번째 요소 선택
// getElementByTagName
// 입력한 Tag명과 일치하는 문서 내의 첫 번째 요소를 반환한다.
// Tag만 가능하다.
const itemTag = document.getElementByTagName('item'); // Tag명이 item인 첫 번째 요소 선택
반응형
갱신 (Update)
// textContent
// 노드의 텍스트를 변경한다.
const oneDiv = document.createElement('div'); // oneDiv 변수에 <div> tag를 생성한다.
oneDiv.textContent = 'hello'; // text를 변수에 추가한다.
console.log(oneDiv); // <div>hello</div>
// classList.add
// 노드에 클래스를 추가한다.
const oneDiv1 = document.createElement('div'); // oneDiv1 변수에 <div> tag를 생성한다.
oneDiv1.classList.add('hi'); // 입력한 선택자를 변수에 추가한다.
console.log(oneDiv1); // <div class="hi">hello</div>
// nodeValue
// 텍스트 노드 객체 값을 반환한다.
// 문서, 요소 노드를 참조하면 null을 반환한다.
const oneDiv = document.createElement('div'); // oneDiv 변수에 <div> tag를 생성한다.
oneDiv.classList('hi'); // <div class="hi"></div>
oneDiv.textContent('hello'); // <div class="hi">hello</div>
const oneDivFirstChild = oneDiv.firstChild; // hello 선택
console.log(document.nodeValue); // null (문서 노드 참조)
console.log(oneDiv.nodeValue); // null (요소 노드 참조)
console.log(oneDivFirstChild.nodeValue); // hello (텍스트 노드 참조)
<!-- replaceChild(newChild, oldChild) -->
<!-- 자신을 호출한 노드의 자식 노드인 oldChild를 newChild 노드로 교체한다. -->
<!DOCTYPE html>
<html>
<body>
<ul id='fruits'>
<li>Apple</li>
</ul>
<body>
<script>
const $fruits = document.getElementById('fruits');
// 기존 노드와 교체할 요소 노드를 생성
const $newChild = document.createElement('li');
$newChild.textContent = 'Banana';
// #fruits 요소 노드의 첫 번째 자식 요소 노드를 $newChild 요소 노드로 교체
$fruits.replaceChild($newChild, $fruits.firstElementChild);
</script>
</html>
// innerHTML
// 요소 노드의 content 영역(테그 시작 ~ 데그 종료 사이) 내에 포함된
// 모든 HTML 마크업을 문자열로 반환한다.
const oneDiv = document.createElement('div'); // oneDiv 변수에 <div> tag를 생성한다.
oneDiv.classList('hi'); // <div class="hi"></div>
oneDiv.textContent('hello '); // <div class="hi">hello </div>
const oneSpan = document.createElement('span'); // oneSapn 변수에 <span> tag를 생성한다.
oneSpan.textContent('world!'); // <span>world!</span>
oneDiv.append(oneSpan); // <div class="hi">hello <span>world!</span></div>
console.log(document.querySelect('.hi').innerHTML);
// "hello <span>world!</span>
<!-- innerHTML 단점 1 -->
<!-- 크로스 사이트 스크립팅 공격에 취약하다. 1 -->
<!DOCTYPE html>
<html>
<body>
<ul id="fruits">
<li class="apple">Apple</li>
</ul>
<body>
<script>
const $fruits = document.getElementById('fruits');
// 노드 추가
$fruits.innerHTML += '<li class="banana">Banana</li>;
// 노드 교체
$fruits.innerHTML = '<li class="banana">Banana</li>;
// 노드 삭제
$fruits.innerHTML += ';
</script>
</html>
<!-- innerHTML 프로퍼티를 사용한 DOM 조작은 구현이 간단하고 직관적이라는 장점이 있지만 -->
<!-- 이렇게 사용자로 부터 입력받은 데이터를 그대로 innerHTML 프로퍼티에 할당하는 것은 -->
<!-- 크로스 사이트 스크립팅 공격(XSS: Cross-Side Scripting Attacks)에 취약하므로 위험하다. -->
<!-- 크로스 사이트 스크립팅 공격에 취약하다. 2 -->
<!DOCTYPE html>
<html>
<body>
<div id="foo">Hello</div>
<body>
<script>
// innerHTML 프로퍼티로 스크립트 태그를 삽입하여 자바스크립트가 실행되도록 한다.
// HTML5는 innerHTML 프로퍼티로 삽입된 script 요소 내의 자바스크립트 코드를 실행하지 않는다.
document.getElementById('foo').innerHTML = '<script>alert(document.cookie)</script>';
// 에러 이벤트를 강제로 발생시켜서 자바스크립트 코드가 실행되도록 한다.
document.getElementById('foo').innerHTML = '<img src="x" onerror="alert(document.cookie)">';
</script>
</html>
<!-- innerHTML 단점 2 -->
<!-- 모든 자식 노드를 제거하고 할당한 HTML 마크업 문자열을 파싱하여 DOM을 변경해서 비효율적이다. -->
<!DOCTYPE html>
<html>
<body>
<ul id = "fruits">
<li class ="apple">Apple</li>
</ul>
<body>
<script>
const $fruits = document.getElementById('fruits');
// 노드 추가
$fruits.innerHTML += '<li class="banana">Banana</li>';
// '<li class="apple">Apple</li>' + '<li class="banana">Banana</li>'
</script>
</html>
<!-- #fruits 요소의 모든 자식 노드(li.apple)를 제거하고 -->
<!-- 새롭게 요소 노드 li.apple과 li.banana를 생성하여 #fruits 요소의 자식 요소로 추가한다. -->
<!-- innerHTML 단점 3 -->
<!-- 새로운 요소 삽입 위치를 지정할 수 없다. -->
<!DOCTYPE html>
<html>
<body>
<ul id = "fruits">
<li class="apple">Apple</li>
<li class="orange">Orange</li>
</ul>
<body>
</html>
<!-- li.apple 요소와 li.orange 요소 사이에 새로운 요소를 삽입하고 싶은 경우 -->
<!-- innerHTML 프로퍼티를 사용하면 삽입 위치를 지정할 수 없다. -->
<!-- innerHTML 프로퍼티를 사용한다면 기존요소를 제거하지 않으면 삽입할 수 없다. -->
<!-- insertAdjacentHTML(position, DOMString) -->
<!-- 기존 요소를 제거하지 않으면서 위치를 지정해 새로운 요소를 삽입한다. -->
<!-- 두 번째 인수로 전달한 HTML 마크업 문자열(DOMString)을 파싱하고 -->
<!-- 그 결과로 생성된 노드를 첫 번째 인수로 전달한 위치(position)에 삽입하여 DOM에 반영한다. -->
<!DOCTYPE html>
<html>
<body>
<!-- beforBegin -->
<div id='foo'>
<!-- afterBegin -->
text
<!-- beforEend -->
</div>
<!-- afterEnd -->
<body>
<script>
const $foo = document.getElementById('foo');
$foo.insertAdjacentHTML('beforeBegin','<p>beforeBegin</p>');
$foo.insertAdjacentHTML('afterBegin','<p>afterBegin</p>');
$foo.insertAdjacentHTML('beforeEnd','<p>beforeEnd</p>');
$foo.insertAdjacentHTML('afterEnd','<p>afterEnd</p>');
</script>
</html>
<!-- innerHTML 프로퍼티보다 효율적이고 빠르다. -->
<!-- 단, innerHTML 프로퍼티와 마찬가지로 insertAdjacentHTML 메서드는 -->
<!-- HTML 마크업 문자열을 파싱하므로 크로스 사이트 스크립팅 공격에 취약하다. -->
삭제 (Delete)
const oneDiv = document.createElement('div'); // oneDiv 변수에 <div> tag를 생성한다.
oneDiv.textContent = 'hello'; // text를 변수에 추가한다.
console.log(oneDiv); // <div>hello</div>
// 방법 1
// remove
oneDiv.remove(); // oneDiv를 전부 삭제한다.
// 방법 2
// removeChild(child)
while(container.firstChild){ // container에 첫 번째 자식이 없을 때까지 삭제한다.
container.removeChild(container.firstChild);
}
// 방법 3
while (container.children.length > 1) { // container의 자식이 하나 남을 때까지 삭제한다.
container.removeChild(container.lastChild);
}
// 방법 4
const greeting = document.querySelectorAll('.hi');
greeting.forEach(function(hi){
greeting.remove(); // class 이름이 hi인 모든 요소를 삭제한다.
})
// 방법 5
const greeting = document.querySelectorAll('.hi');
for (let hi of greeting){
hi.remove() // class 이름이 hi인 모든 요소를 삭제한다.
}
적용 (Append)
const oneDiv = document.createElement('div'); // oneDiv 변수에 <div> tag를 생성한다.
oneDiv.textContent = 'hello'; // text를 변수에 추가한다.
console.log(oneDiv); // <div>hello</div>
// append
container.append(oneDiv); // container에 변수 oneDiv를 적용시킨다.
document.body.append(oneDiv); // body에 변수 oneDiv를 적용시킨다.
// appendChild
container.appendChild(oneDiv); // container에 변수 oneDiv를 마지막 자식 요소로 추가한다.
DOM (2)을 알아보는 시간이었습니다.
틀린 내용은 댓글로 알려주시면 감사하겠습니다.
반응형