NomadCoder - Vanila JS로 크롬 앱 만들기🔥
<모던 자바스크립트 Deep Dive> 라는 책으로 Js를 조금 해놔서 그런지? 수월하게 진행할 수 있었습니다! 모든 내용을 기록하지는 않을거고 (전체 수업 내용 실습 코드는 Git에 푸쉬해놨습니디 :D) 공부를 하면서 새롭게 알게된 핵심 내용 위주로 기록해보겠습니다. ⭐️ 오늘도 화이팅 ⭐️
console 창에서 document 를 치면? html(index.html 파일 자체)를
보여준다 => 작성한 html을 가져온다.
이 말인 즉슨, document가 브라우저에 이미 존재하는 객체(object)라는 의미이다 접근할 수 있는, 접근 가능한 html을 가리키는 객체.
documnet는 그저 객체일 뿐이다. 정말 무수히 많은 정보들이 들어가있는 객체
=> 우리의 웹 사이트를 의미한다. (이는 console.dir 로 확인 가능하다.)
console.log 와 console.dir 의 차이는 무엇인가요?
- console.log는 요소(element)를 HTML과 같은 트리 구조로 출력 하고, DOM 요소에 대한 특별한 처리를 제공합니다.
- console.dir은 요소를 JSON과 같은 트리 구조로 출력 하고, DOM JS 객체의 전체 표현을 보려고 할 때 유용합니다.
객체는 dir, 나머지는 log로 이해하면 편합니다 .
console.log의 경우 해당 body의 요소가 출력 되고, console.dir의 경우 전체 요소가 출력됩니다.
document 정보에 보면
documnet.title = "Momentum" 이라고 나온다. 내 코드(실습)에서는 #3이 뜨겠지? (내가 그렇게 해줬으니까 ㅋ) 이것은 아주 아주 굉장히 흥미로운 내용이다. (선생님이 그랬음 나는 도대체 뭐가 흥미로운건지 모르겠음)
=> title 이라는 항목(요소,element)은 js가 아니라? html에 내가 정의한 항목이기 때문이다. JS에서 title을 정의하지 않았다.
결론 = document 가 html을 보여주는 거다.
But JS의 관점으로 보여진다 => "object로 보인다"
핵심은? "JS에서 HTML document 객체(Object)로부터 title을 가지고 올 수 있다. => 매우 중요한 개념
JS는 HTML에 접근하고 읽을 수 있게 설정이 되어있다.JS는 HTML을 읽어온다. 여기서 알 수 있듯이 HTML 코드를 JS 관점에서 보고있다. Object에서 properties 를 가지고 올 수 있다.
만약에 콘솔창에서 document.title = "Hi" 하면? 값이 바뀐다. JS 에서 HTML을 읽어올 뿐만 아니라 값을 바꿀 수도 있다(새로고침하면 다시 이전으로 돌아가긴 하지만..)
HTML과 JS를 따로 연결(Connection)해줄 필요가 전혀 없다. 자동으로 이미 연결이 다 되어 있다. 그렇다면 JS로 HTML에 있는 정보를 가지고 올 수 있는 방법은? 메소드(Method)!! JS에서 document와 그 안의 element들을 가지고 오는 함수들을 쓰는 것이다.
Document.getElementById() 메서드는 주어진 문자열과 일치하는 id 속성을 가진 요소를 찾고, 이를 나타내는 Element 객체를 반환한다. ID는 문서 내에서 유일해야 하기 때문에 특정 요소를 빠르게 찾을 때 유용하다.
function changeColor(newColor) {
var elem = document.getElementById('para');
elem.style.color = newColor;
}
JS에서 document 객체의 요소(element)에 접근해서 그 값을 바꾸고 있다.
=> 이번 포스팅의 마지막에 설명!! 가장 중요한..?? 핵심입니다. 끝까지 봐주세요🔥
Document 인터페이스의 getElementsByTagName 메소드는 엘리먼트의 HTMLCollection 과 주어진 태그명을 반환한다. 루트 노드를 포함해 전체 다큐먼트를 대상으로 검색된다. 반환된 HTMLCollection 은 살아있는데, 이는 document.getElementsByTagName() 을 다시 호출하지 않아도 자동으로 업데이트하여 DOM 트리와 동기화된 상태를 유지함을 의미한다.
var elements = document.getElementsByTagName(name);
Element의 메소드 getElementsByClassName() 는 주어진 클래스를 가진 모든 자식 엘리먼트의 실시간 HTMLCollection 을 반환한다.
var elements = element.getElementsByClassName(names);
// 아래의 예시는 main 이라는 id 를 가진 요소의 하위 요소들 중
// test라는 클래스를 가진 모든 요소를 탐색한다.
document.getElementById('main').getElementsByClassName('test');
이것들 전부 좋긴한데... 상황마다 다르게 써야된다는게 불편하지 않으신가요?
불편하다고 하세요 빨리
이것들을 대신에서 쓸 수 있는게 바로 쿼리셀렉터(Qeury Selector)입니다!!
document의 element를 가지고 오는 여러가지 방법 중 가장 멋진 방법
Document.querySelector()는 제공한 선택자 또는 선택자 뭉치와 일치하는 문서 내 첫 번째 Element를 반환한다. 일치하는 요소가 없으면 null을 반환한다.
참고: 탐색은 깊이우선depth-first (DFS) 전위pre-order순회로, 문서의 첫 번째 요소부터 시작해 자식 노드의 수를 기준으로 순회합니다.
querySelector 매우 중요!! 거의 맨날 이거만 쓸거에요. 이게 제일 편하더라구요♥️
const titless = document.querySelector(".hello h1")
querySelector : CSS 방식으로 검색 가능
hello 라는 class 내부에 있는 h1을 가지고 올 수 있다는 걸 의미
querySelector는 단 하나의 element만 리턴한다. 조건에 맞는 element가 여러 개면 제일 첫 번째꺼만 나온다.
querySelectorAll은 전부 다 나옴 => 배열(Array) 반환
id 를 통해서 값을 찾고 싶더라도 document.getElementById 안하고 querySelector 쓸거임
document.qeurySelector(#title)
id는 #붙여주면 되고 class는 . 붙여주면 됩니다!!
// 좀 더 복잡한 선택자
// 아래 예제처럼 정말 강력한 선택자도 사용할 수 있다.
// 예제의 결과는 클래스가 "user-panel main"인
// <div>(<div class="user-panel main">) 안의,
// 이름이 "login"인 <input> 중 첫 번째 요소
var el = document.querySelector("div.user-panel.main input[name=login]");
const title_change = document.querySelector(".hello:first-child h1")
console.log("title_change => ",title_change);
title_change.style.color = "blue";
// h1의 style을 js에서 변경할 수 있다는 사실이 중요
// js 에서 발생하는 event를 여기서 listen 하는게 중요
function handleTitleClick(){
console.log("title was clicked");
title.style.color="red";
}
title_change.addEventListener("click", handleTitleClick);
title_change.onclick = handleTitleClick
// 이 2개가 동일한 기능!!
오른쪽 인자(parameter)에 handleTitleClick() 하면 그냥 바로 실행을 하라는건데.. 우리가 하고 싶은건! 그게 아니라 함수만 넘겨주고 js 에서 함수 실행함. 이 함수를 곧바로 실행하는게 아니라 click을 할 때만 실행!! 일반적으로 알고 있는거 처럼 굳이 버튼일 필요가 없다. 태그들(h1, h2 ~)에도 가능!!
function handleMouseEnter(){
title_change.innerText = "Mouse is here!!";
}
title_change.addEventListener("mouseenter", handleMouseEnter);
title_change.onmouseenter = handleMouseEnter;
// 2개가 같은 기능(마우스가 그 위로 올라가면, => hover)
function handleMouseLeave(){
title_change.innerText = "Mouse is gone!!";
}
title_change.addEventListener("mouseleave", handleMouseLeave);
// 지금 상태 : 3개의 이벤트가 동시에 발생(병렬적으로)
그럼 2개가 기능이 똑같은데 굳이 addEventListener를 쓰는 이유는?
=> removeEventListener를 통해서 event listener를 제거할 수 있다
function handleWindowResize(){
document.body.style.backgroundColor = "tomato";
}
window.addEventListener("resize", handleWindowResize)
// title_change 처럼 document 안에 있는 h1 같은 element 는 안돼
// window 정도의 사이즈? 폼? 에서만 가능
function handleWindowCopy(){
alert("Copier!!");
}
window.addEventListener("copy", handleWindowCopy);
// 객체가 윈도우여도 패턴은 똑같다
// element를 찾아서 event listener를 추가하고, event가 발생하면 반응을 해준다.
알아두면 좋을 다른 신기한 기능들
function handleWindowOffline(){
alert("SOS no wifi");
}
function handleWindowOnline(){
alert("All Good");
}
widdow.addEventListener("offline", handleWindowOffline);
widdow.addEventListener("online", handleWindowOnline);
정말 유용하게, 자주 쓰는 토글에 대해서 알아보자
title을 한번 클릭하면 토마토로 색깔 바뀌고, 다시 한번 더 누르면 파란색으로 바뀌게 하고 싶다 => 토글(Toggle)
const title_change = document.querySelector(".hello:first-child h1")
console.log("title_change => ",title_change);
title_change.style.color = "blue";
// h1의 style을 js에서 변경할 수 있다는 사실이 중요
// HTML에서 발생하는 event를 여기서(JS에서) listen 하는게 중요
function handleTitleClick(){
console.log("title_change.style.color => " , title_change.style.color);
// 이걸 getter 라고 함
title_change.style.color="red";
// 이걸 setter 라고 함
console.log("title_change.style.color => ", title_change.style.color);
if(title_change.style.color === "blue"){
title_change.style.color = "tomato";
}
else {
title_change.style.color = "blue";
}
console.log("title_change.style.color => ", title_change.style.color);
이까지 좋아 기능이 잘 되니까, 근데 title_change.style.color 이걸 너무 많이 쓰네 ..
좀 번거롭지? => 변수로 지정해서 현재 색깔을 저장해주자
const currentColor = title_change.style.color;
let newColor;
// const와는 달리 let으로 선언한 변수는 값이 변경될 수 있다.
if(currentColor === "blue"){
newColor = "tomato";
}
else {
newColor = "blue";
}
title_change.style.color = newColor;
하.. 진짜 다 좋은데 css를 자꾸 js에서 바꾸려고 하면 안돼
그럼 style.css 파일은 왜 있냐고
title_change.className = "active";
// 이렇게 하면 js가 css와 직접 대화하지 않는다
// js 는 html을 변경할거고 (html 에 h1 태그 className을 변경)
// CSS 는 html 을 바라보고 있다.
// 위에 코드보단 이게 확실히 더 좋다. 왜냐면 더 작은 js 코드로 동일한 결과니까
// 이제 title_change의 className을 왔다리 갔다리 하고 싶어
if(title_change.className === "active"){
title_change.className = "";
}
else {
title_change.className = "active"
}
// 토글 똑같이 구현
// 하지만 이 코드는 아직 에러가 나올 가능성이 있다
// active 는 내가 만들어준거고 2번이나 사용됨
// 이걸 바꾸고 싶을 때 위 아래가 철자 틀린거 하나 없이똑같이 바꿔줘야 해
const clickedClass = "active";
if(title_change.className === clickedClass){
title_change.className = "";
}
else {
title_change.className = clickedClass;
}
// 버그를 고치는 방법 1 (사전에 예방하는 방법)
// 두 번째로 발생 가능한 버그는?
// 처음에 className이 없는 상태로 시작하면 이게 맞다
// 근데 className 이 있는 상태(토글 클래스 말고
// 폰트에 관한 클래스가 하나 더 있는)로 시작하면? 버그!!
// sexy-font를 clickedClass 로 교체해버림 해결 방법은?
// classList 사용하기!!!
const clickedClass = "active";
if(title_change.classList.contains(clickedClass)){
title_change.classList.remove(clickedClass);
}
else {
title_change.classList.add(clickedClass);
}
// 이렇게하면 sexy-font는 그대로 내두고? active 만 생겼다 없어졌다 한다.
// 하지만 이건 개발자들이 매일 같이 항상 하는 일이다.
// 이걸 편리하게 해줄 함수를 만들어 놓지는 않았을까?
// => toggle function
// toggle function은 바로 위의 if-else 코드를 구현해놓은 것이다.
const clickedClass = "active";
title_change.classList.toggle(clickedClass);
// title_change의 classList에 clickedClass가 없으면 추가, 있으면 제거
// 졸라 좋다. 졸라 편하다.
// 결론!!! 앞에 내용들을 다 이해하고, 사용은 toggle을 쓰기!!
// 공식문서에 나오는 toggle의 정의
// =>toggles token, removing it,
// if it is present and adding if it is not
title_change.addEventListener("click", handleTitleClick);
이제 본격적으로 application 만들기 시작하자!!!!!!!!!!