DOM
학습 목표
DOM 이란..?
Document Object Model의 약자로, HTML(Document)에 접근하여 Object(JavaScript Object)처럼 HTML을 조작(Manipulation)할 수 있는 Model이라는 의미 만약 자바스크립트를 사용하는 방법을 알고 있으면 DOM을 활용하여 HTML을 조작할 수 있다. 즉 DOM 은 HTML 의 아주 작은 부분까지 접근하여 조작할 수 있도록 웹페이지를 철저히 분석하여 준비된 구조로, 자바스트립트는 이 구조를 활용하여 HTML 로 구성된 웹 페이지를 작동할 수 있게 만들어 준다.
MDN에서 Introduction to the DOM 검색해 보기!!
DOM은 HTML 문서의 프로그래밍 interface 이다. 구조화된 nodes, property, method 를 갖고 있는 objects 문서를 표현한다. 이들은 웹 페이지를 스크립트 또는 프로그래밍 언어들에서 사용될 수 있게 연결시켜주는 역할을 담당한다.
페이지 컨텐츠는 DOM에 저장되고, 자바스크립트를 통해 접근하거나 조작할 수 있다.
API(web or XML page) = DOM + JS(scripting language)
CRUD
Document 객체를 통해서 HTML 엘리먼트를
C : Create 만들고
R : read 조회하고
U : Update 갱신하고
D : Delete 삭제하고
HTML 조작하기
학습 목표
DOM을 JavaScript로 조작하여 HTML Element를 추가하거나 삭제, 혹은 내용을 변경할 수 있다.
<template>: The Content Template element<template> 요소는 페이지를 불러온 순간 즉시 그려지지는 않지만, 이후 JavaScript를 사용해 인스턴스를 생성할 수 있는 HTML 코드를 담을 방법을 제공합니다.Create : createElement
const tweetDiv = document.createElement('div')
하지만 이 상태는 공중에 떠 있는 것처럼 아무것도 연결되어 있는 것이 없다. 이 엘리먼트를 append 해 주어야 웹 상에서도 구동 가능하다.
Append : append, appendChild
아래 명령어를 통해 tweeDiv를 body 안에 넣기.
document.body.append(tweetDiv)
콘솔창에 가보면 div 가 새로 생긴것을 확인할 수 있다.

혼자 공부하기
prepend : ParentNode.prepend() 메소드는 Node 객체 또는DOMString 객체를 ParentNode의 첫 자식노드 앞에 삽입한다. DOMString 객체는 Text 노드와 동일하게 삽입된다.let parent = document.createElement("div");
let p = document.createElement("p");
let span = document.createElement("span");
parent.append(p);
parent.prepend(span);
console.log(parent.childNodes); // NodeList [ <span>, <p> ]
append : ParentNode.append() 메서드는 ParentNode의 마지막 자식 뒤에 Node 객체 또는 DOMString 객체를 삽입한다. DOMString 객체는 Text 노드처럼 삽입한다.
Node.appendChild()와 다른 점:
-> ParentNode.append()는 DOMString 객체도 추가할 수 있다. 한편 Node.appendChild()는 오직 Node 객체만 허용한다.
-> ParentNode.append()는 반환하는 값이 없다. 한편 Node.appendChild()는 추가한 Node 객체를 반환한다.
-> ParentNode.append()는 여러 개 노드와 문자를 추가할 수 있다. 한편 Node.appendChild()는 오직 노드 하나만 추가할 수 있다.
document.getElementById("yourId").appendChild("<p></p>"); // 이렇게는 안됨
var p = document.createElement("p");
document.getElementById("yourId").appendChild(p); //이렇게 해야 함
결론은 appendChild 를 쓸 수 있는 모든 상황에서는 append도 사용할 수 있지만, 그 반대는 안됨.
Read : querySelector, querySelectorAll
querySelector 를 사용하도록 하며, (querySelector는 한글로 셀렉터를 기반으로 한 질문을 한다, 쿼리를 날린다라는 의미) '.tweet' 을 첫 번째 인자로 넣으면 tweet을 클레스 이름으로 가진 모든 HTML 엘리먼트를 조회할 수 있다.const oneTweet = document.querySelector('.tweet') ///하나만 조회
const tweets = document.querySelectorAll('.tweet') ///다 조회
All을 덧붙여야 tweet이란 클래스를 가진 모든 요소를 조회할 수 있으며, 이렇게 조회해온 HTML엘리먼트들은 배열과 유사하게 for 문을 사용할 수 있다. 이런 '배열 아닌 배열'은 유사배열, 배열형 객체 등 다양한 이름으로 불리며, MDN에서 Working with array-like objects 검색해 보기.
검색결과 배열 처름 행동하기는 하지만 모든 method 가 먹히는 건 아니라고 함.
아래와 같이 get 으로 시작하는 것들은 옛날 익스플로러 방식
const getOneTweet = document.getElementById('container')
const queryOneTweet = document.querySelector('#container')
console.log(getOneTweet === queryOneTweet) // true
아래와 같은 명령어를 통해 위에서 생성한 tweet을 추가할 수 있다.
const container = document.querySelector('#container')
const tweetDiv = document.createElement('div')
container.append(tweetDiv)
MDN에서 querySelector 검색해서 아래 공부해 보기
UPDATE - textContent, classList.add
div 를 하나 만들었고,
const oneDiv = document.createElement('div')
console.log(oneDiv) // <div></div>
text를 넣어보고
oneDiv.textContent = 'dev';
console.log(oneDiv) // <div>dev</div>
class 를 지정
oneDiv.classList.add('tweet')
console.log(oneDiv) // <div class="tweet">dev</div>
append로 container에 붙이기
const container = document.querySelector('#container')
container.append(oneDiv)
-> console 창에 차례대로 실습해 보기
혼자 공부하기
setAttribute 라는 메소드를 검색해보기var b = document.querySelector("button");
b.setAttribute("name", "helloButton"); // 기존 '버튼' 이던걸 '헬로버튼'으로 이름을 바꿈
b.setAttribute("disabled", ""); // 조금이라도 속성이 존재한다면 boolean 에서 true 로 간주. 근데 이번 예시는 무슨 뜻인지 모르게뜸...
textContent와 innerHTML의 차이 (difference between textContent and innerHTML)innerHTML의 보안상 단점 (mdn innerHTML security issue)DELETE - remove, removeChild
삭제하는 방법도 여러가지가 있다.
우선 해당 엘리먼트가 어디 있는지 알고 있는 경우
const container = document.querySelector('#container')
const tweetDiv = document.createElement('div')
container.append(tweetDiv)
tweetDiv.remove() // 이렇게 append 했던 엘리먼트를 삭제할 수 있다.
자식 엘리먼트 지우기 : innerHTML을 활용하면 간단하지만, 보안상의 문제가 있다. 상기 혼자 공부하기 내용 참조
document.querySelector('#container').innerHTML = '';
그래서 메소드를 활용. remoeChild는 자식 엘리먼트를 지정해서 삭제하는 방식이고, 모두 삭제하고 싶다면 while 문을 활용할 수 있다. 자식 엘리먼트가 하나도 없을때 까지 삭제한다는 의미.
const container = document.querySelector('#container');
while (container.firstChild) {
container.removeChild(container.firstChild);
}
이렇게 지우면 H2 Tweet list까지 싹 지워지기 때문에, 마지막 자식을 하나 남기거나, 직접 일일히 찾아서 지울수 도 있다.
const container = document.querySelector('#container');
while (container.children.length > 1) {
container.removeChild(container.lastChild);
} // 한놈만 남기기
const tweets = document.querySelectorAll('.tweet')
tweets.forEach(function(tweet){
tweet.remove();
})
// or
for (let tweet of tweets){
tweet.remove()
} // 일일히 다 지우기
또 혼자 공부하기. 그냥 다 혼자 공부하기
element와 node의 차이 (difference between element and node in javascript dom)
-> Node 는 DOM 계층에 있는 오브젝트 타입의 어떤 일반적인 이름이다. 노드는 DOM 요소의 뭐라도 될 수 있다. such as document, document.body, textnode, HTML tag가 될 수도 있고, 또 다른 element 안의 text block 도 될수 있고. 뭐 졸라 많네.. 무튼 간단히 말하면 노드는 뭐 어떤 DOM object 임.
반면, element 는 노드 안에서 어떤 특정 타입밖에 될 수 없음. 이런 DOM 은 부모가 되기도 하고, 자식이 되기도 하고, 앞에도 있고 뒤에도 있는 이런 노드 계층으로 구성되어 있음. 그래서 나무 계층 구조라고 하는 거임. element 는 어떤 특정 타입의 노드를 가리키는 거임. 그래서 노드가 엘리먼트보다 더 큰 범주.
children과 childNodes의 차이 (difference between children and childNodes in javascript dom)
-> childNodes : childNodes 는 노드의 속성을 지니고 있는데, 이것은 nodelist 를 리턴하고, 이 node list 는 string 이 아닌 onject 임. 따라서 인덱스 넘버로 엑세스 할 수 있음.
-> children은 엘리먼드의 속성을 지니고 있음.
-> 이 둘의 main defference 는 children 은 오직 엘리먼트의 속성만 지니고 있는 반면, childNode는 텍스트나 comment node 처럼 non-element 적인 노드도 포함하고 있음
removeChild와 remove의 차이 (difference between removeChild and remove in javascript dom)
-> 일단 기본적으로 remove 라고 하면 진짜 제거하는 줄 알고 있는데 그게 아니다.
-> 근데 사실은 remove의 컨셉은 진짜 없애버리는게 아니라, 부모 자식간의 관계를 끊어버리는 거다.
-> 이 둘을 썻을 때 결과는 동일하지만, remove 는 자식만 reference 하고, removeChild는 부모 자식 모두를 reference 한다.

tweets에 forEach는 되는데, reduce는 안되는 이유 (why array method is not working on nodelist)
-> forEach & reduce 모두 array 에 사용하는 method 인데, 이 둘의 성격을 정확히 모르겠으므로 검색해 봐도 모르게따...
tweets를 유사 배열에서 배열로 바꾸는 방법 (how to convert nodelist into javascript array)
-> 일단 바꾸는 방법을 확인하기에 앞서,
-> 노드 리스트는 DOM element 에 접근하고 다룰 수 있는 어떤 노드 collection 임. 반면 자바스크립트에서의 array는 한번에 한개 이상의 value를 가질 수 있음. 노드 리스트 & 어레이 둘다 스스로의 prototype, method, property 를 가지고 있음.
-> 노드 리스를 어레이 인 자바스크립트로 바꾸는 가장 쉬운 방법은 Array.from()을 쓰는 거임. 그러나 옛날 브라우저에서는 안 먹힘
-> spread syntax 도 됨. const divsArr = [...divs]; 처럼. 근데 이것도 옛날 브라우저는 안 먹힘
-> 그래서 Array.prototype.slice()를 쓰면 됨. 이건 옛날 브라우저도 먹힘.