24/4/9 바닐라 자바스트립트
2024. 4. 9. 23:01ㆍ카테고리 없음
코딩테스트 갔다가 부딪힌 바닐라 자바스크립트
난 참패 했다. react랑 next만 들여다 보고 바닐라 자바스크립트를 소홀히 했기 때문에 일어난 대참사였다.
애초에 작년 10월부터 코딩을 시작했으면서 뭔 자신감으로 바닐라를 무시한건지... 븅딱이다.
html요소를 끌어와야 되는데 document.querySelector 나 document.getElementById 의 document가
생각이 안나서 15분동안 html.getElementById 이었나??? 아닌뎅? body.queryselector인가? 이러면서
땀만 흘리고 있었다. 반성의 의미로 시작된 바닐라 조지기 프로젝트 출발한다.
노마드 코더님의 자바스크립트로 크롬앱만들기 클론코딩
<index.html>
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="css/style.css" /> //css 파일 불러오기
<title>바닐라 자바스크립트</title>
</head>
<body>
<form class="hidden" id="loginForm"> //hidden 이라는 class에 display : none을 주어
<input //기본적으로 보이지 않는 form 태그
required //required 를 주어서 input태그에 value가 반드시 있어야 됨
maxlength="15" //최대 길이값을 설정
type="text" //이건 뭐 안줘도 된다. type으로 input의 종류가 달라진다.
placeholder="넌 이름이 뭐니?" //value가 없을때 보여지는 안내문 정도?
/>
<button>로그인</button>
</form>
<h1 id="greet" class="hidden"></h1>
<h2 id="clock"></h2>
<div id="weather">
<span></span>
<span></span>
</div>
<a href="about.html">어바웃으로</a> //html간의 이동방식 주로 앵커태그를 이용
<form id="todoform"><input type="text" placeholder="작성하세용" /></form>
<ul id="todoList"></ul>
<div id="quote">
<span></span>
<span></span>
</div>
<script src="./js/app.js"></script>
<script src="./js/clock.js"></script>
<script src="./js/quote.js"></script>
<script src="./js/backGround.js"></script>
<script src="./js/todo.js"></script>
<script src="./js/weather.js"></script>
</body>
</html>
<app.js>로그인의 기본적인 동작원리를 다룬 js
const loginForm = document.querySelector("#loginForm"); //tag를 가져오는 방식 쿼리셀렉터 이다
const loginInput = document.querySelector("#loginForm input"); //태그에 id이름으로 끌어올려면 #샵을
const greet = document.querySelector("#greet"); //클래스로 가져올려면 .온점을 사용하고
const link = document.querySelector("a"); //해당네임을 가져온다.
const HIDDEN_CLASS = "hidden";
const USER_NAME = "username"; //휴먼에러를 줄이기 위한 상수의 변수 선언
const onLoginSubmit = function (tomato) { //로그인은 기본적으로 form태그를 이용한다.
tomato.preventDefault(); //폼태그는 submit속성의 버튼 클릭시 자동새로고침된다.
loginForm.classList.add(HIDDEN_CLASS); //preventDefault 로 새로고침을 막는다.
const username = loginInput.value; //위에서 끌어온 로그인폼에 classList.add를 통해
console.log(username); //특정 클래스명을 추가해주고 인풋의 value를 따로 담아둔다.
localStorage.setItem(USER_NAME, username); //새로고침시 날아가버리는 data를 보관하기 위한
faintGreet(username); //로컬스토리지
}; //faint는 말고 paint인데 귀찮아서 놔둠 ㅋ
const linkHandler = (event) => { //a태그도 기본적으로 새로고침 기능이 있다.
// event.preventDefault();
console.log(event);
alert("click");
};
link.addEventListener("click", linkHandler); //쿼리셀렉터로 끌어온 link에 클릭기능을 달아주자
//첫번째 인자는 이벤트 종류 // 두번째는 함수이다. const savedUsername = localStorage.getItem(USER_NAME); //로컬스토리지에 저장된 key에 해당하는
function faintGreet(username) { //값을 불러오는 getItem
greet.classList.remove(HIDDEN_CLASS); //add와는 반대로 remove는 해당 class명을 지운다.
greet.innerHTML = `hello ${username}`; //해당 태그에 내부 글자를 바꾸는 innerHTML
}
if (savedUsername === null) { //로컬스토리지에 해당 벨류가 없다면 발생된다.
loginForm.classList.remove(HIDDEN_CLASS); //로그인폼에서 hidden class를 제외시켜서 보이게 한다.
loginForm.addEventListener("submit", onLoginSubmit); //그와 동시에 서브밋 기능을 붙인다.
} else {
faintGreet(savedUsername); //로컬스토리지에 값이 있다면 인사를 날린다.
}
<backGround.js>배경넣는 방식의 근본
const images = ["river.jpg", "lake.jpg", "tree.jpg"]; //넣을 이미지 파일의 name이다.
const chosenImage = images[parseInt(Math.random() * images.length)]; //배경을 랜덤으로 바꿀 예정인데
//0~1까지의 무작위수를 받아서 요래요래 하면 0,1,2의 정수가뿅console.log(chosenImage);
const image = document.createElement("img"); //태그 자체를 생성하는 creatElement
image.src = `img/${chosenImage}`; //방금만든 태그에 src속성을 달아준다. 실제 이미지 파일명을 제공
console.log(image);
document.body.appendChild(image); //이제 html body에 appendChild를 통해 가장 아래 태그로 붙여준다.
//앞쪽에 붙이기 위해서는 prepend를 사용한다고 한다.
<clock.js> 예쁜 시계를 달아보자.
const clock = document.querySelector("#clock"); //역시나 querySelctor로 해당 태그를 끌어온다.
clock.innerHTML = "00:00"; 일단 기본값을 요래 둔다.
function getClock() { //시계의 동작원리를 담을 함수
const date = new Date(); //Date오브젝트를 통해 date를 찍어내주자.
const hours = String(date.getHours()).padStart(2, "0"); //date는 여러 매서드를 갖는데
const minutes = String(date.getMinutes()).padStart(2, "0"); //시각을 가져오고 분을 가져오고 초를 get어쩌구로
const seconds = String(date.getSeconds()).padStart(2, "0"); //가져온다. padStart는 해당 문자열을 조건에
clock.innerHTML = `${hours}:${minutes}:${seconds}`; //맞춰서 반환해준다.
} //마지막에 잘 할당한 시 분 초를 태그에 붙여주면 끝
getClock();
setInterval(getClock, 1000); //setInterval 함수는 두개의 인자를 받는다 처음은 작동할 콜백함수
// setTimeout(sayHello, 5000); //두번째는 얼마나 시간텀을 두고 작동할지 결정하는 시간이다.
<quote.js> 교훈을 보여줘 보자
const quotes = [ //스스로에게 날리는 매콤한 교훈 진짜 정신차리자
{ content: "정신차리고 코드나 쳐!!!", person: "한지우" },
{ content: "세상이 만만하냐? 똑바로 안살래?", person: "한지우" },
{ content: "게을러 터져져 어쩔려고 그러냐?", person: "한지우" },
{ content: "정신 안차리면 너 굶어 뒤진다?", person: "한지우" },
{ content: "코딩공부 열심히 해라 그거라도 안하면 뭐할래?", person: "한지우" },
];
const quote = document.querySelector("#quote span:first-child"); //역시나 id로 태그불러오는데
const person = document.querySelector("#quote span:last-child"); //공백두고 자식태그를 불러온수 있다.
//첫째와 막내 span을 맛깔나게 불러오자.const randomQuote = parseInt(Math.random() * quotes.length); //시계랑 똑같은 랜덤 불러오기 0~4사이의 정수
console.log(randomQuote);
console.log(quotes[randomQuote]);
quote.innerHTML = quotes[randomQuote].content; //그렇게 랜덤하게 불러온 quote를 내용과 사람 분류해서
person.innerText = quotes[randomQuote].person; //할당한다.
<weather.js> 오픈 API를 불러오는 근본 외부통신의 기초이다.
const API_KEY = "이건 API키야 쿠쿠루삥뽕"; //API를 따로 할당해 보았다.
const geoOkay = (position) => { //position이라는 매개변수를 받는다. 네이밍은 상관엄슴
const la = position.coords.latitude; //위도와 경도를 할당한다.
const lo = position.coords.longitude;
console.log(lo, la);
let URL = `https://api.openweathermap.org/data/2.5/weather?lat=${la}&lon=${lo}&appid=${API_KEY}&units=metric`;
console.log(URL); //URL은 다 다르다. 얘네는 이렇게 제공한다.
fetch(URL) //fetch를 통해 비동기적으로 API데이터를 가져와 본다.
.then((res) => res.json()) //then을 통해 비동기 data수신 완료후 작업을 진행한다. fetch는 json형식변환 필!!
.then((data) => { //한번더 then을 써서 파싱된 데이터를 추후 작업한다.
let city = document.querySelectorAll("#weather span:first-child"); //쿼리셀렉터 ALL을 그냥 쿼리셀렉터랑
let weather = document.querySelectorAll("#weather span:last-child"); //다르게 배열로 가져오니까 유의
// console.log(city, " t시티");
city[0].innerText = data.name; //이제 이너 텍스트든 이너 HTML이든 써써
weather[0].innerText = data.weather[0].main; //할당해주면 끝
});
};
const geoError = function () {
alert("오우 에러");
};
navigator.geolocation.getCurrentPosition(geoOkay, geoError); //사실 요게 중요하다.
//요걸 쓰면 이제 현재 유저의 위치정보를 받아올수 있다. 인자로는 첫번째는 성공시 콜백함수고 //두번째는 실패시 이뤄지는 콜백함수다. 걍 유저가 위치제공 승낙하는지 안하는지로 나눠진다.
<todo.js> 투두리스트를 만들어보자 뭐 CRUD의 기초가 담겼다. 쿠쿠루삥뽕
const todoForm = document.getElementById("todoform"); //getElement바이로 가져와봄 #은 노필요
const todoList = document.querySelector("#todoList");
const todoInput = todoForm.querySelector("input"); //태그종류 자체를 가져오기 때문에 태그명 쓴다.
const TODOS_KEY = "Todos";
let Todos = []; //투두들을 담을 어레이
const saveTodos = () => { //로컬스토리지에 저장할 함수
localStorage.setItem("Todos", JSON.stringify(Todos)); //배열형태인 todos를 안망가뜨리고
}; //로컬스토리지에 저장하기위한 stringify
function deleteTodo(event) { //삭제함수
const li = event.target.parentNode; //해당이벤트의 target인 버튼태그의 부모노드를 할당
li.remove(); //지워버림 remove로
console.dir(li.id);
const arr = Todos.filter((item) => { //태그는 지워 졌지만 로컬스토리지에서도 지워야함
return item.id != li.id; //필터링을 통해 todos배열의 item의 id와 삭제버튼의 부모노드
}); //인 li에 id를 비교해서 다른애들만 남긴다 즉 일치하는애 삭제
// console.log(arr);
Todos = arr; //그렇게 필터링된애로 재할당하고
saveTodos(); //로컬스토리지를 업데이트한다.
}
const paintTodo = (newTodo) => { //새로운 todo를 그리기 위한 함수
// console.log(newTodo);
const li = document.createElement("li"); //li태그를 야무지게 생성한다.
const span = document.createElement("span");
const button = document.createElement("button"); //요 태그들도 야무지게 생성한다.
button.innerText = "✖"; //버튼태그의 안에 text를 할당
button.addEventListener("click", deleteTodo); //그와 동시에 삭제 함수를 클릭이벤트에 할당
li.appendChild(span);
li.appendChild(button); //li태그에 이제 span과 버튼태그를 붙여준다.
li.id = newTodo.id; //매개변수인 newTodo에는 id랑 text가 들어있다 오브젝트다.
span.innerText = newTodo.text;
todoList.appendChild(li); //todolist에 이제 li태그를 붙여줘서 마무리
};
const submitHandler = function (event) { //그림을 그리는 위에 함수와는 별개로 //제출로직이 담긴함수
event.preventDefault(); //폼태그이기 때문에 새로고침 막고
const newTodo = todoInput.value; //인풋태그의 정보를 미리 받아두고
todoInput.value = ""; //제출했응께 인풋태그 비워주고
const newObj = { //이게 위에 페인트 todo에서 받은 매개변수가될 오브젝트
text: newTodo,
id: Date.now(), //id와 text를 갖는다. id는 단순하게 날짜로 한다 ㅋ
};
Todos.push(newObj); //todos어레이에 담아주고
saveTodos(); //로컬스토리지에 저장해주고
paintTodo(newObj); //동시에 정보 정리가 잘 끝나고 그림을 그린다.
};
todoForm.addEventListener("submit", submitHandler); //폼태그에 서브밋 이벤트를 담아준다.
function saysay(item) { //얜 뭐냐 ㅋ
console.log(item, " zz");
}
const getSavedTodos = localStorage.getItem(TODOS_KEY); //자바스크립트의 첫랜더링시
// console.log(getSavedTodos); //해당 키값을 확인해본다.
if (getSavedTodos !== null) { //키에 해당하는 벨류가 있다면
const parsedTodos = JSON.parse(getSavedTodos); //json형식으로 저장된 arr를 파싱해서 가져와서
// console.log(parsedTodos);
Todos = parsedTodos; //todos의 배열에 할당해주고
parsedTodos.forEach(paintTodo); //todos배열에 각아이템을 순회하면서 작동하는 배열매서드를 이용
} //해서 그림을 그려준다.
const sexyfilter = function (item) { 필터링 테스트
return item % 2 === 0;
};
const res = [1, 2, 3, 4].filter(sexyfilter); //소괄호 없이 함수명만 달아보는건 안익숙해서 해봄 ㅋ
console.log(res);
이상으로 바닐라 자바스크립의 기초를 다시 해보았다.
결론 재밌당. ㅋㅋ