< Window 객체 >
- window 객체는 브라우저에 의해 자동으로 생성되며 웹 브라우저의 창(window)를 나타낸다. 또한 window는 브라우저의 객체이지 javascript 객체가 아니다.
- 이 window 객체를 이용해서
1. 브라우저의 창에 대한 정보를 알 수 있고, 이 창을 제어하고 할 수도 있다.
2. 또한 var 키워드로 변수를 선언하거나 함수를 선언하면 이 window 객체의 프로퍼티가 된다.
(ex)
- var 로 선언해서 window 객체의 프로퍼티를 만들어야 한다. let과 const는 블록 스코프이기에 window 객체 내부의 블록에서 선언된 것으로 전역 객체의 프로퍼티로 활용될 수 없다.(아래)
< Dom 이란? >
- 브라우저에서 UI를 볼 수 있는 것은 HTML의 요소를 하나하나 분석해서 보여준 것이다.
- 돔(문서 객체 모델)은 메모리에 웹 페이지 문서 구조를 트리구조로 표현해서 웹 브라우저가 HTML 페이지를 인식하게 해준다.
- 위에서 보는 웹 페이지를 이루는 요소들을 자바스크립트가 이용할 수 있게끔 브라우저가 트리구조를 만든 객체 모델을 의미한다.
- 실제 순서는 브라우저가 HTML을 분석해서 DOM 트리를 만든 다음에, 이를 토대로 페이지에 띄워주는 로직이다.
[ 돔 조작 ]
- 위에 보이는 DOM 트리를 DOM에서 제공하는 API를 이용해서 조작할 수 있다.
- API를 이용해서 DOM 구조에 접근하거나 원하는 요소(Element)를 수정하거나 삭제할 수 있다. 이러한 동작을 자바스크립트 코드에서 작성함으로써 수행한다.
예를 들어, HTML 코드가 아래와 같다고 하면,
<button class = "button"> Allu Coding </button>
JS 코드는 아래와 같이 작성할 수 있다.
// DOM 안에 클래스가 button 이라는 이름을 가진 요소에 접근
var button = document.querySelector('.button');
// DOM 안에 있는 요소의 스타일을 직접 변경(DOM 조작)
button.onclick = function(){
this.style.backgroundColor = "red";
};
- 자바스크립트 코드 안에 있지만 실제 document.querySelector 부분은 자바스크립트 자체 요소는 아니다. document 브라우저에서 제공하는 window 객체의 한 부분이다.
그렇다면, 이렇게 DOM 을 조작해서 화면을 변경시켜줄 때 브라우저 내부에서는 어떠한 과정을 통해서 바뀐 화면을 변경시켜주는지 알아보자!
< 웹 페이지 빌드 과정(Critical Rendering Path CRP) >
- 브라우저가 서버에서 페이지에 대한 HTML 응답을 받고 화면에 표시하기 전에 여러 단계가 있다.
- 웹 브라우저가 HTML 문서를 읽고, 스타일 입히고 뷰포트에 표시하는 과정이다.
※ CSS 객체 모델(CSSOM)
- CSS Object Model은 JavaScript에서 CSS를 조작할 수 있는 API 집합이다. HTML 대신 CSS가 대상인 DOM이라고 생각할 수 있으며, 사용자가 CSS 스타일을 동적으로 읽고 수정할 수 있는 방법이다.
- 위의 웹 페이지 빌드 과정에서, DOM과 CSSDOM을 렌더링하는 부분은 비용이 많이 들지 않더라도, Render Tree나 Layout이 짜여지고 그려지는 부분은 비용이 많이 들기에 이 부분을 최소화 하는 것이 성능의 척도이다.
(React 에서는 Virtual Dom을 만들어 가지고 이런 부분을 최소화해준다.)
< Document Object 이용해보기 >
- window 객체가 브라우저 창이라고 하면, document 객체는 브라우저 내에서 콘텐츠를 보여주는 웹 페이지 자체라고 할 수 있다.
[ Document 객체 프러퍼티 사용]
- document 객체를 이용해서 웹페이지의 상태와 모든 HTML 태그들에 접근할 수 있다.
[ Document 객체 메소드 사용]
- document 객체의 메소드들을 사용하면 다양한 방법으로 웹페이지 내의 태그들에 접근할 수 있다.
- 밑에서부터는 해당 html 을 가지고 예제를 적용할 것이다.
<!DOCTYPE html>
<html lang="en">
<head>
<title>Document Object</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js"></script>
</head>
<body>
<div id="header-container" class="container-fluid p-5 bg-primary text-white text-center">
<h1 id="header-heading" class="header-title">My First Bootstrap Page</h1>
<h5>Resize this responsive page to see the effect!</h5>
</div>
<div id="body-container" class="container mt-5">
<div class="row">
<div class="col-sm-4">
<h3>Column 1</h3>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit...</p>
<p>Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris...</p>
</div>
<div class="col-sm-4">
<h3>Column 2</h3>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit...</p>
<p>Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris...</p>
</div>
<div class="col-sm-4">
<h3>Column 3</h3>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit...</p>
<p>Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris...</p>
</div>
</div>
<form class="form-container" action="/action_page.php">
<div id="form-first-div" class="mb-3 mt-3">
<label for="email" class="form-label">Email:</label>
<input type="email" class="form-control" id="email" placeholder="Enter email" name="email">
</div>
<div class="mb-3">
<label for="pwd" class="form-label">Password:</label>
<input type="password" class="form-control" id="pwd" placeholder="Enter password" name="pswd">
</div>
<div class="form-check mb-3">
<label class="form-check-label">
<input class="form-check-input" type="checkbox" name="remember"> Remember me
</label>
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
<ul class="list-group mt-5 mb-5">
<li class="list-group-item">An item</li>
<li class="list-group-item">A second item</li>
<li class="list-group-item">A third item</li>
<li class="list-group-item">A fourth item</li>
<li class="list-group-item">And a fifth one</li>
</ul>
<div id='container'>
innerHTML innerText textContent 차이점
<span style='display:none'>안보이는 텍스트</span>
</div>
</div>
<script src="script1.js"></script>
<script src="script2.js"></script>
</body>
</html>
- 하나의 요소에 접근
// 파라미터로 전달한 ID를 가진 태그를 반환
document.getElementById(요소아이디);
// 파라미터로 전달한 name 속성을 가진 태그를 반환
document.getElementByName(name속성값);
// 파라미터로 전달한 선택자에 맞는 첫 번째 태그를 반환
document.querySelector(선택자);
// document.getElementById()
console.log(document.getElementById('header-container'));
console.log(document.getElementById('header-heading').className);
const headerContainer = document.getElementById('header-container');
// styling 변경
headerContainer.style.fontsize = '10px';
headerContainer.style.display = 'none';
// content 변경
headerContainer.textContent = 'Text Content';
headerContainer.innerText = 'Inner Text';
headerContainer.innerHTML = '<span style="color:blue">Inner HTML</span>';
// document.querySelector()
console.log(document.querySelector('#form-first-div'));
console.log(document.querySelector('.form-container'));
console.log(document.querySelector('h5'));
document.querySelector('li').style.color = 'green';
document.querySelector('ul li').style.color = 'pink';
document.querySelector('li:last-child').style.color = 'red';
document.querySelector('li:nth-child(2)').style.color = 'blue';
document.querySelector('li:nth-child(4)').textContent = 'ALLU CODING';
document.querySelector('li:nth-child(odd)').style.backgorund = 'gray';
document.querySelector('li:nth-child(even)').style.backgorund = 'lighgray';
- 여러 요소에 접근
// 파라미터로 전달한 태그이름을 가진 모든 태그들을 반환(배열)
document.getElementsByTagName(태그이름)
// 파라미터로 전달한 클래스 이름을 가진 모든 태그들을 반환(배열)
document.getElementsByClassName(클래스이름)
// 파라미터로 전달한 선택자에 맞는 모든 태그들을 반환(배열)
document.querySeletorAll(선택자)
// document.getElementsByClassName
const items = document.getElementsByClassName('list-group-item');
console.log(items);
console.log(items[0]);
items[0].style.color = 'green';
items[3].textContent = 'Allu';
// document.getElementsByTagName
let list = document.getElementsByTagName('li');
console.log(list);
console.log(list[0]);
list[0].style.color = 'pink';
list[3].textContent = 'Coding';
// HTML 모음을 배열로 만들기
list = Array.from(list);
list.reverse();
list.forEach(function(li,index){
console.log(li.className);
li.textContent = `${index}. List`;
});
console.log(list);
// document.querySelectorAll
const items = document.querySelectorAll('ul.list-group li.list-group-item');
items.forEach(function(item,index){
item.textContent = `${index}. List`;
});
const liOdd = document.querySelectorAll('li:nth-child(odd)');
const liEven = document.querySelectorAll('li:nth-child(even)');
liOdd.forEach(function (li,index){
li.style.background = 'lightgray';
});
for (let i=0;i< liEven.length; i++){
liEven[i].style.background = 'gray';
}
console.log(items);
[ innerHTML vs innerText vs textContent ]
- innerHTML 은 html 까지 같이 보여준다.
- innerText는 사용자에게 보여지는 텍스트 값을 읽어오며 여러 공백은 무시하고 하나의 공백만 처리한다. ( html에서 작성할 때, 스페이스 공백이 많아도 사용자에게는 공백 하나로 보여지는 것처럼 사용자에게 보여지는 그대로 보여진다.)
- textContent는 display:none 스타일이 적용된 숨겨진 텍스트도 가져오는 노드가 가지고 있는 텍스트 값 그대로 보여준다. ( html에서 작성한 그대로가 보여진다고 보면 된다.)
< Dom 탐색하기 >
- DOM을 이용하면 요소와 요소의 콘텐츠에 무엇이든 할 수 있다. 하지만, 무언가를 하기 전에, 우리가 조작하고자 하는 DOM 객체에 접근하는 것이 선행되어야 한다.
- DOM에 수행하는 모든 연산은 document 객체에서 시작한다. document 객체는 DOM에 접근하기 위한 '진입점' 일 뿐이다.
- 진입점을 통과하면 그 어떤 노드에도 접근할 수 있는 셈이다.
[ 자식 노드 탐색하기 ]
- childNodes, firstChild, lastChild 로 자식노드를 탐색할 수 있다.
- 밑에서부터는 해당 html 을 가지고 예제를 적용할 것이다.
<!DOCTYPE html>
<html lang="en">
<head>
<title>Dom Traverse</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js"></script>
</head>
<body>
<div id="body-container" class="container mt-5">
<ul class="list-group mt-5 mb-5">
<li class="list-group-item 1">An item</li>
<li class="list-group-item 2">A second item</li>
<li class="list-group-item 3">A third item</li>
<li class="list-group-item 4">A fourth item</li>
<li class="list-group-item 5">And a fifth one</li>
</ul>
</div>
<script src="script.js"></script>
</body>
</html>
let val;
const list = document.querySelector('ul.list-group');
const listItem = document.querySelector('li.list-group-item:first-child');
val = listItem;
val = list;
// child nodes 반환
val = list.childNodes;
val = list.childNodes[0];
val = list.childNodes[0].nodeName;
val = list.childNodes[3];
val = list.childNodes[3].nodeType;
// //nodeType
// 1 - Element
// 2 - Attribute
// 3 - Text node
// 8 - Comment <!-- Comment Node -->
// 9 - Document itself
// 10 - Doctype
// children element nodes 반환
val = list.children; // HTML Collection을 반환(line break 포함 x)
val = list.children[1];
list.children[1].textContent = 'Hi';
// First child
val = list.firstChild;
val = list.firstElementChild; // text node를 포함 x
// Last child
val = list.lastChild;
val = list.lastElementChild;
// child 요소 count
val = list.childElementCount;
// parent node 반환
val = listItem.parentNode;
val = listItem.parentElement;
val = listItem.parentElement.parentElement;
// next sibling 반환
val = listItem.nextSibling;
val = listItem.nextElementSibling;
val = listItem.nextElementSibling.nextElementSibling;
val = listItem.nextElementSibling.nextElementSibling.previousElementSibling;
// previous sibling 반환
val = listItem.previousSibling;
val = listItem.previousElementSibling;
console.log(val);
- 자식 노드 : 바로 아래의 자식 요소를 나타낸다.
- 후손 노드 : 중첩 관계에 있는 모든 요소를 의미한다. 자식 노드와 그 보다 자식 노드 모두가 후손 노드가 된다.
[ DOM 컬렉션 ]
- childNodes는 마치 배열 같아 보인다.
- 하지만, childNodes는 배열이 아닌 반복 가능한(iterable) 유사 배열 객체인 컬렉션(Collection) 이다.
- childNodes 가 컬렉션이기에 가지는 특징
- 비록 배열은 아니지만, forEach(), for ... of 를 사용할 수 있다. ( for ... in 은 사용 불가하다.)
2. 배열이 아니기에 배열 메서드 사용 불가능하다.
3. 위의 경우에 배열 메서드를 사용하고 싶다면, Array.from 을 사용하면 진짜 배열을 만들 수 있다.
< CreateElement >
- 요소를 생성할 때, html 에서 바로 태그를 생성해도 되지만, 자바스크립트로 생성할 수 있다.
- document.createElement(tagName); 처럼 createElement 메서드에 태그 이름을 넣어서 요소를 생성할 수 있다.
- 밑에서부터는 해당 html 을 가지고 예제를 적용할 것이다.
<!DOCTYPE html>
<html lang="en">
<head>
<title>CreateElement</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.2/font/bootstrap-icons.css">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js"></script>
</head>
<body>
<div id="body-container" class="container mt-5">
<ul class="list-group mt-5 mb-5">
<li class="list-group-item">An item</li>
<li class="list-group-item">A second item</li>
</ul>
</div>
<script src="script.js"></script>
</body>
</html>
// element 생성
const li = document.createElement('li');
// class 추가하기
li.className = 'list-group-item';
// id 추가하기
li.id = 'new-item';
// attribute 추가하기
li.setAttribute('name','New list itme');
// 새로운 text node 생성하고 더하기
li.appendChild(document.createTextNode('New list item '));
// 새로운 link element 생성하기
const link = document.createElement('a');
// classes 추가하기
link.className = 'alarm-item';
// icon html 추가하기
link.innerHTML = '<id class="bi-alarm"></i>';
// link를 li에 더하기
li.appendChild(link);
// li 를 ul의 자식으로 더하기
document.querySelector('ul.list-group').appendChild(li);
console.log(li);
< removeChild & replaceChild >
- 자바스크립트로 요소를 생성하는 것도 있겠지만, 삭제하고 교체하는 것도 있다.
- 밑에서부터는 해당 html 을 가지고 예제를 적용할 것이다.
<!DOCTYPE html>
<html lang="en">
<head>
<title>Remove, Replace</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.2/font/bootstrap-icons.css">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js"></script>
</head>
<body>
<div id="body-container" class="container mt-5">
<ul class="list-group mt-5 mb-5">
<li class="list-group-item">An item</li>
<li class="list-group-item">A second item</li>
</ul>
<div id="A">Hello</div>
</div>
<script src="script.js"></script>
</body>
</html>
[ removeChild ]
- parentNode.removeChild(node);
- 하나의 노드를 삭제한다.
- 삭제할 때는 삭제 할 노드를 자식으로 가진 부모 노드에서 실행된다.
const listParent = document.querySelector('ul');
const list = document.querySelectorAll('li');
listParent.removeChild(list[1]);
[ replaceChild ]
- parentNode.replaceChild(new Child, old Child);
- 원래 있는 Child를 삭제하고 새 Child로 교체한다.
- 교체할 때는 교체할 노드를 자식으로 가진 부모 노드에서 실행된다.
const oldElement = document.getElementById('A');
const newElement = document.createElement('span');
newElement.textContent = "Allu";
oldElement.parentNode.replaceChild(newElement, oldElement);
참고 자료
따라하며 배우는 자바스크립트 A-Z
'컴퓨터 공부 > 🕸️ Web' 카테고리의 다른 글
Javascript 중급 - 1) this, bind, call, apply, 동기/비동기, call stack, call back (0) | 2023.12.04 |
---|---|
Javascript 기본 - 3) Event (0) | 2023.12.01 |
Javascript 에서 forEach 함수는 비동기함수를 기다리지 않아요! (0) | 2023.11.29 |
Javascript 기본 - 1) 자바스크립트 JS 기초 (0) | 2023.11.29 |
Javascript 에서의 setInterval(함수,간격) (0) | 2021.05.29 |