문서 객체 모델 Document Object Model
웹페이지의 구조와 내용을 구성하는 데이터를 객체화하여 메모리에 저장
javascript를 통해 html의 요소를 Object처럼 제어할 수 있는 인터페이스
-> 웹페이지 동적으로 기능 추가 가능
-> DOM API : DOM에 접근/변경하기 위한 프로퍼티와 메소드의 집합
DOM 트리(html의 계층구조)
: html의 요소인 객체와 노드로 웹페이지 표현
document객체 : 웹 페이지
-> 요소에 접근하려면 document로 시작(최상위 노드)
html에 자바스크립트 적용하는 태그
<script src="myScriptFile.js"></script>
<script>
등장 후 바로 실행
: 웹브라우저는 <script>
를 만나면 html parsing은 잠시 멈추고 <script>
내용을 먼저 실행
<head>
태그 내에서 선언
<body>
태그 내부 끝에서 선언
console.log('welcome JavaScript');
let msgElement = document.querySelector('#msg');
console.log(msgElement);
/* head 태그에서 실행되는 경우 두번째 콘솔에서 null 출력됨 */
console.dir()
: DOM 객체로 출력
DOM으로 자식태그 찾기
children
속성을 이용
document.body.children;
// body태그의 자식태그 조회
DOM으로 부모태그 찾기
parentElement
속성을 이용
const newsContents = document.body.children[1];
newContents.parentElement;
html에서 태그의 클래스,id명 찾는 수도코드
function consoleLogAllElement(element){
// nav의 class 이름을 console.log 합니다.
// nav의 자식 엘리먼트가 있는지 검색합니다. (logo, menu-wrapper)
//logo의 class 이름을 console.log 합니다.
//logo의 자식 엘리먼트가 있는지 검색합니다. (없음)
//menu-wrapper의 class 이름을 console.log 합니다.
//menu-wrapper의 자식 엘리먼트가 있는지 검색합니다. (menu, menu, menu, profile-photo)
//첫 번째 menu의 class 이름을 console.log 합니다.
//첫 번째 menu의 자식 엘리먼트가 있는지 검색합니다. (없음)
//두 번째 menu의 class 이름을 console.log 합니다.
//두 번째 menu의 자식 엘리먼트가 있는지 검색합니다. (없음)
//세 번째 menu의 class 이름을 console.log 합니다.
//세 번째 menu의 자식 엘리먼트가 있는지 검색합니다. (없음)
//profile-photo의 class 이름을 console.log 합니다.
//profile-photo의 자식 엘리먼트가 있는지 검색합니다 (없음)
//자식 엘리먼트를 모두 탐색했음으로, 함수 실행이 종료됩니다.
//자식 엘리먼트를 모두 탐색했음으로, 함수 실행이 종료됩니다.
}
CRUD + append
DOM으로 html의 새로운 요소 생성
createElement()
document.createElement('div');
// <div></div>
// 노드가 연결되지 않은 상태 -> append 작업 필요
DOM으로 노드를 부모 노드와 연결
-> 트리구조에 연결 : 연결 후 화면에 보임
append()
const div = document.createElement('div');
document.body.append(div);
// <body>에 div 요소를 연결
// 비어있는 <div>에 내용이 추가되면 웹페이지에서도 보임 -> update 작업 필요
DOM으로 html 요소 조회 & 선택
: 대상을 조회 후 트리구조에 연결(append 작업)
CSS selector를 기준으로 접근
querySelector()
: 셀렉터 요소 중 가장 먼저 위치한 정보 하나를 조회querySelectorAll()
: 전체 셀렉터 요소를 조회
-> 유사 배열(노드 객체)로 반환
-> for 반복문 활용getElementById()
등
cf. 동일한 기능인get~
는 오래된 방식(호환성을 위해 사용)
제어대상 차이점 알아보기
document.querySelector('.tweet');
// 클래스명이 tweet인 요소 선택
/*
1. 추가할 요소 생성 + 문서에서 대상을 선택
2. append 작업으로 DOM에 노드 연결
*/
const container = document.querySelector('.container');
const tweetDiv = document.createElement('div');
container.append(tweetDiv);
DOM으로 html 요소를 수정
textContent
속성 : 콘텐츠의 텍스트 변경(자식 노드의 텍스트 포함)classList.add()
: 클래스 추가setAttribute()
: 입력한 속성 추가/변경const oneDiv = document.createElement('div');
console.log(oneDiv) // <div></div>
/* 텍스트 변경 */
oneDiv.textContent = 'dev';
console.log(oneDiv) // <div>dev</div>
/* 클래스 추가 */
oneDiv.classList.add('tweet');
console.log(oneDiv); // <div class="tweet">dev</div>
cf.
innerText
속성 : 렌더링 된 텍스트 만을 표시(숨겨진 요소 제외), 수정시 자식 노드 제거
innerHTML
속성 : HTML, XML문자열을 조회/수정 -> 보안 이슈 발생 : textContent
권장
insertAdjacentHTML(position, text)
: HTML, XML문자열을 특정 위치에 추가(수정 X)
document.write(markup)
: 로딩할 때 실행되면 가장 먼저 데이터를 출력, 로드 후 사용하면 문서의 모든 내용을 지우고 입력데이터 출력(덮어씌어짐) -> 사용시 주의!!
setAttribute()
: 태그에 속성을 추가 / 수정
cf.getAttribute()
는 속성 조회,removeAttribute()
는 속성 제거setAttribute(name, value) // name : 태그의 속성(소문자 변환) // value : 태그 속성의 속성값(문자열 변환)
/* <button>Hello World</button>일 때 */ var b = document.querySelector("button"); b.setAttribute("name", "helloButton"); // <button name="helloButton">Hello World</button>
DOM으로 html 요소를 제거
remove()
: 요소의 위치를 알고, append 했던 요소 제거 removeChild()
: 자식 요소를 제거document.querySelector('#container').innerHTML = '';
const container = document.querySelector('.container');
const tweetDiv = document.createElement('div');
container.append(tweetDiv);
/* append 했던 요소 하나를 제거 */
tweetDiv.remove();
/* 컨테이너id의 자식요소 전체 제거 */
// case 1 -> 보안이슈 발생
document.querySelector('.container').innerHTML = '';
// case 2 : container에 첫번째 자식요소가 있으면 요소 제거
while(container.firstChild){
container.removeChild(container.firstChild);
/* 제목 남기고 자식요소 전체 제거*/
while(container.children.length >1){
container.removeChild(container.lastChild);
}
/* 특정 클래스 전체 지우기 */
// case 1
const tweets = document.querySelectorAll('.tweet')
tweets.forEach(function(tweet){
tweet.remove();
})
// case 2
for (let tweet of tweets){
tweet.remove();
}
느낀점
너무 피곤하다.. 분명 수업 자체는 이번주에 어렵지는 않았는데, 블로깅하고 헷갈리는 부분 서치 하는게 너무 많다. 오늘도 6시간정도 할당되어있는데 4시간정도에 끝낸고, 나머지 알아지는 비교해보고, mdn 문서 보다가 시간 다 가는 것 같다. 그런데 자습하는건 좋은데 mdn이 잘 이해가 안가서 모호하게 읽힌다. 결국 다른 문서를 또 찾아본다. 가장 필요한 언어는 영어고..;;
DOM부분 예전부터 궁금했는데 그때 서치하니까 안보이더니 이번에 구글링 하니까 자료가 많더라; 아무튼 getElementById()나 getElementsByClassName() 이것들이 더 구체적이니까 더 선호되는 메서드인줄 알았는데, 이번 수업을 들으니 QuerySelector들을 더 권장하는 것 같아서 의외였다. 스파르타에서는 get메서드들을 사용해서 더 선호하는 방식인줄 알았는데. 수업을 들으면 들을수록 실무에 더 적합한 방식을 배우는 것 같아서 좋다. 정리할건 많지만 그만큼 배운거니까!!
개선점 및 리마인드