본문 바로가기
Programming/Front-end

[자바스크립트] 기초 클론코딩 (노마드 코더 Vanilla JS)

by Renechoi 2022. 10. 16.

 

[자바스크립트] 기초 클론코딩 (노마드 코더 Vanilla JS)

 

 

 

Const and let 

 

자바스크립트에서는 2가지 방식으로 변수 설정

 

const = 상수로 설정 

let =새로운 것을 생성할 때 사용 (처음에만)

const a = 5;

let myNmae = "C"

myName = "D"

Const 설정한 변수에 대해서는 바꾸지 못한다. 

 

(Var은 자바스크립트에서 옛날 버전에 사용) 

 

 

 

 

 

할당 

 

 

const a = false;

const nothing = null;	
let something;

 

null 값은 어떤 것이 없다는 것을 확실히 할 때 

something = 그냥 변수를 만들어주고 값 자체가 없음 = 비어있음 = undefined 

 

 

 

 

자바스크립트에서 Object 

 

 

const player = {
    name : "C",
    points : 10,
    fat : true,

}

console.log(player);
console.log(player.name);
console.log(player["name"]);

player.lastName = "potato";	#새로운 것을 추가할 수도 있다.

 

 

 

자바스크립트 Function 

 

const player = {
    name : "N",
    sayHello : function(otherPersonName){
        console.log("hello" + otherPersonName);
    },
}


player.sayHello("judy")

 

console에 출력되는 간단한 계산기 

 

const calculator = {
    plus : function (a,b ){
        console.log(a+b);
    },

    minus : function(a,b){
        console.log(a-b);
    },

    divide : function(a,b){
        consol.log(a / b);
    },

    power : function(a,b){
        console.log(a ** b);
    },
}


calculator.plus(2,3);

 

 

 

자바스크립트에서 type를 보는 아주 고전적인 방법 

 

const age = prompt("How old are you?")

console.log(typeof age)

 

 

 

자바스크립트에서 if 문 

 

const age = parseInt ( prompt("How old are you?") ) 

console.log(isNan (age))


if (isNan(age)){
    console.log("please write a number");
}   else if (age < 18){
    console.log("you are too young");
}
    else if (age >= 18 && age < 50){
    console.log("you can drink");
}
    else {
    console.log("thank you !");
}

 

 


 

자바스크립트에서는 document를 object로 인식한다.

 

document.title => html에서 규정한 title을 가져옴. 

 

바꿀 수도 있음 ! 

 

 

컨셉 : 

 

1) html을 가져오고 

2) html을 바꾼다 

 

 

 

QuerySelector

 

element를 CSS 방식으로 가져올 수 있다. 

 

const hellos = document.querySelector(".hello h1");

위와 같은 코드로 html에서 특정 인자를 가져올 수 있다 

<div class="hello">
        <h1>Grab me!</h1>
    </div>

QuerySelector는 오직 첫번째 것만 가져옴 

 

전부 가져오려면 querySelectorAll = array로 가져옴 

 

 

 

 

 

이벤트와 listen

 

 

const title = document.querySelector("div.hello:first-child h1");


function handleTitleClick(){
    console.log("title was clcked!");
}

title.addEventListener("click", handleTitleClick);

 

 

 


자바스크립트에서 반응에 따른 변화 만들기 



자바스크립트에서 print = 
console.log()

 

 


function handleTitleClick(){

    const currentColor = h1.style.color;
    let newColor;

    if (currentColor === "blue"){
        newColor = "tomato";
    } else{
        newColor = "blue";
    }
    h1.style.color = newColor;
}

 

 


하지만 색깔은 js가 아니라 css에서 바꿔주는 게 좋다

 



CSS 설정 

 

.active { 
    color : tomato;
}

 

function handleTitleClick(){
    h1.className = "active";        // 여기서 js는 html과만 소통 => classname을 바꿔준다 => 그러면 css에서 설정한 것에 따라 = active 설정 => 색깔이 바뀐다
                                    
}

 

부드러운 효과 

.active { 
    color : tomato;
    transition: color 0.5s ease-in-out;
}

 

 



function handleTitleClick(){
    if (h1.className === "active"){
        h1.className = "";
    } else {
        h1.className = "active";
    }

}


=> 좀 더 클린하게 

1) clicked되는 기능을 정의한 raw 네임을 변수화함 => const clickedClass 

2) html에서 정의한 본 class 네임이 훼손되는 부분의 문제 해결 필요성 => 
classList를 사용해서 contain 여부로 마일드하게 바꿔줌 

 

 

 

function handleTitleClick(){
    const clickedClass = "clicked";

    if (h1.classList.contains(clickedClass)){
        h1.classList.remove(clickedClass);
    } else {
        h1.classList.add(clickedClass);
    }

}

 

 

 

 

기존의 classname을 살리면서 효과가 들어갈 때 추가하는 방식으로 바꿀 수 있다 


사실 토글 함수가 이미 있어서 굳이  이렇게 쓸 필요가 없다. 

 

 

function handleTitleClick(){
    h1.classList.toggle("clicked");
}
h1.addEventListener("click", handleTitleClick);

 

 


// https://developer.mozilla.org/en-US/docs/Web/API/Element
// console.dir(h1)  // <= element를 보여줌으로써 어떤 이벤트 찾을지 알려줄 수 

 

 

 


유저 로그인 기능 


원래의 방법 

 


const loginInput = document.querySelector("#login-form input");
const loginButton = document.querySelector("#login-form button");

function onLoginBtnClick(){
    const username = loginInput.value;
    if (username ===""){
        alert("Please write your name");
    } else if (username.length > 15){
        alert("Your name is too long");

    }
    console.dir(loginInput.value);
}

loginButton.addEventListener("click", onLoginBtnClick);

 

BUT Html에서 input 조건을 넣어줄 수 있다. 

form 형식으로 바꾸고 버튼 형식이 아닌 submit 방식으로 바꿔준다. 

    <form id = "login-form">
        <input 
            required 
            maxlength="15"           
            type="text" 
            placeholder="what is your name?"
            />
        <input type="submit" value ="Log In" />
    </form>


그런데 문제는 브라우저는 기본 function으로 form을 submit하면 계속 리프레시 시킨다 

그걸 제어하기 위해 자바스크립트에서 기본으로 들어가고 있는 object 변수를 설정해주고 = event라고 conventional 하게 설정 

function onLoginSubmit(event){
    event.preventDefault();
    const username = loginInput.value;
    console.log(username);
}



event.preventDefault(); 이 코드로 기본 기능을 막는다 





input 창에 쓴 글자 로그인 버튼 이후 사라지게 하기 

css에서 hidden 기능 만들어주고 이벤트 발생시 히든시키는 기능으로 연결한다 



function onLoginSubmit(event){
    event.preventDefault();
    const username = loginInput.value;
    loginForm.classList.add("hidden");
    console.log(loginInput.value);
}

 

전체가 다 사라지는 문제가 발생 => 

html에서 새로 h1 태그 만들어주고 히든처리할 것과 살릴 것을 구분시킨다 

그리고 js에서 이렇게 변경 

 

 

 

const HIDDEN_CLASSNAME = "hidden";  // String 컨텐츠 담을 때는 대문자로 변수 정한다 

function onLoginSubmit(event){
    event.preventDefault();
    loginForm.classList.add(HIDDEN_CLASSNAME);
    const username = loginInput.value;
    greeting.innerText = "Hello " + username;
    greeting.classList.remove(HIDDEN_CLASSNAME);
}

 

 




Saving user name => 한번 저장된 유저는 기억하는 기능 구현 

=> local storage를 사용한다 

 


기본 로직 슈도코드 

 

 

const savedUsername =localStorage.getItem(USERNAME_KEY);

if ( savedUsername === null){
    // show the form 
} else
    // show the greeting 



반복되는 것 함수로 바꿔주고 


function paintGreetings(username){
    greeting.innerText = `hello ${username}`  ;
    greeting.classList.remove(HIDDEN_CLASSNAME);

}


const savedUsername =localStorage.getItem(USERNAME_KEY);

if ( savedUsername === null){
    loginForm.classList.remove(HIDDEN_CLASSNAME);    // html에서 기본 form 도 히든으로 처리했기 때문에 저장이 안되어있는 경우 히든 기능을 제거 = 보이게 함 
} else{
   paintGreetings(username=savedUsername);
}

 

 

 




다음 진도로 나가기 전에 폴더 정리 

css, js 폴더 별도 생성 
app.js 이름을 greetings.js로 바꿔주고 
clock.js 생성 

 

 



특정 시간 마다 실행하는 함수  => setInterval(sayHello, 5000);

특정 시간 후에 실행하는 함수 => setTimeout(sayHello, 5000)



 

 



function getClock(){
    const date = new Date();
    const hours = String(date.getHours()).padStart(2, "0");             // 00:00:00 형식을 맞춰주기 위해 스트링 + 패딩 작업 
    const minutes = String(date.getMinutes()).padStart(2, "0");
    const seconds = String(date.getSeconds()).padStart(2, "0");

    clock.innerText = `${hours}:${minutes}:${seconds}`;
}

getClock(); // 바로 시작할 때 호출 
setInterval(getClock, 1000);    // 1초에 한번씩 초를 갱신

 

 

 



자바스크립트에서 숫자 관련 함수 

math.random() * 10 => 0 ~ 10까지의 숫자 

math.round(1.1) 반올림 
math.ceil(1.6) 올림
math.floor(1.3) 내림 

 

 

 

랜덤으로 컨텐츠를 생성하고 출력해주는 것 구현 

  const quote = document.querySelector("#quote span:first-child");
  const author = document.querySelector("#quote span:last-child");
  const todaysQuote = quotes[Math.floor(Math.random() * quotes.length)];    
  
  quote.innerText = todaysQuote.quote;
  author.innerText = todaysQuote.author;

 

 

 


배경을 가져오는 것도 동일하다 

가져온 배경을 html에 넣기 

나와야 하는 형식 = 
<img src="img/0.jpg" />


이번에 변수 생성할때는 createElement("img); 를 씀 

const bgImage = document.createElement("img")

이 명령어로 img 컨텐츠를 임의로 생성할 수 있음 

bgImage.src = `img/${chosenImage}`

이것을 html body에 넣어주어야 한다 

간단한 명령어로 가능

document.body.appendChild(bgImage);

 




todolist 만들기 

기본적으로 아이디 받는 기능과 비슷하다 



form으로 만들어주고 
iput 받음 

ul태그로 빈 태그 만들어줌 


    <form id ="todo-form">
        <input type="tett" placeholder="Write a Todo and Press Enter" required />
    </form>
    <ul id="todo-list"></ul>

 


자바스크립트에서 똑같이 구현 

const toDoForm =document.getElementById("todo-form");
const toDoInput = toDoForm.querySelector("input");
const toDoList =document.getElementById("todo-list");


function handleToDoSubmit(event){
    event.preventDefault();
    toDoInput.value = "";           // 쓴 것을 지워주는 기능 
}

toDoForm.addEventListener("submit", handleToDoSubmit)

 

 

 

 



받은 변수 저장하기 

function handleToDoSubmit(event){
    event.preventDefault();
    const newTodo =toDoInput.value;         // 변수를 저장해 두고 
    toDoInput.value = "";                   // 지움으로써 저장해둔 변수에는 변함이 없도록 한다 
}

toDoForm.addEventListener("submit", handleToDoSubmit)




Todo에 페인트할 함수 생성 

얘가 하는 일은 html <li> 태그에 represent 할 것을 만들고 뭔가를 하는 것 = 백그라운드 설정할 때 body 에 새로운 것을 만들어주었듯이 

 

 


function paintToDo(newTodo){
    const li = document.createElement("li")     // 변수 이름 자체를 li로 만들어줄 필요는 없음 
    const span = document.createElement("span")
    li.appendChild(span);       // li 태그 밑에 span을 넣어줌 = 나중에 버튼을 넣을 것을 고려해서 li에 그냥 문자열이 들어가지 않고 span을 통해 들어가게 함  
    span.innerText = newTodo;
}

 

 

 


함수에 받은 newTodo가 사용자가 입력한 String

마지막으로 html에 represnet 하기 위해
toDoList.appendChild(li);



이때 두가지 문제 해결 해야 함 

1) 새로고침하면 없어지는 문제
2) 쓴 걸 다시 지울 수도 있도록 하는 기능 

 

 



delete 기능 구현하기 위해 먼저 버튼 생성 

html에 명시적으로 넣어주고 

    <ul id="todo-list">
        <li>
            <span>text</span>
            <button>X</button>
        </li>
    </ul>

js에서 똑같이 createElement 해줌 


function paintToDo(newTodo){
    const li = document.createElement("li");     
    const span = document.createElement("span");
    const button = document.createElement(("button"));
    button.innerText="❌"
    li.appendChild(span);     
    li.appendChild(button);
    span.innerText = newTodo;
    toDoList.appendChild(li);
}

 

 




다음으로는 버튼이 클릭되면 지워지도록 하는 기능 
= 간단하게 event 리스닝과 function으로 가능한데 

문제는 어떤 게 어떤 것인지 세부적으로 조정할 필요가 있음 

=> 클릭될때 js가 갖고 있는 이벤트 정보를 갖고 어떤 게 어떤 건지를 볼 수 있음 
= event 가 갖고 있는 property 중 target으로 

로직 : parentElement를 찾으면 이벤트가 발생할때 어떤 타겟으로 되는지를 알 수 있다 = 삭제해야 할 것 지목 가능 => 변수로 만들고 삭제하면 됨 

 

function deleteToDo(event){
   const li= event.target.parentElement;
   li.remove();
}

 

 

 




todo를 저장하기 

array를 만들어주고 push해주고 localStorage에 저장하는 방식 


const toDos = []; 

function saveToDos(){
    localStorage.setItem("todos", toDos);
}

하지만 이때 가져올 때 string으로 가져오고 싶다면 
JSON.stringify(); 로 저장해 배열 그대로 storage에 저장한다 

    localStorage.setItem("todos", JSON.stringify(toDos));

string으로 된 것을 다시 JSON.parse 하면 => object 형식으로 바뀜 
인덱스가 있는 오브젝트 

 

 



object array로 된 것을 개별적으로 컨트롤 하고 싶다면 
function으로 넘겨줄 때 event 정보를 보면 된다 <= 중요한 기능 ! 


 parsedToDos.forEach(); 

 이 함수로 각각의 객체들에 대한 접근 + 새로운 function으로 하나하나 컨트롤 

array function으로 좀 더 간단하게도 가능하다 


    parsedToDos.forEach( (item) => console.log("this is the turn of"), item);



원하는 기능 = 저장된 것을 보이게 하는 것이기 때문에 

parsedToDos.forEach( (paintToDo));



여기서 문제는 const toDos = [];  항상 빈 array를 선언해놓았기 때문에 리프레쉬 할때마다 localStorage는 다시 덮어써진다 


let toDos = []; 
변수로 바꾸고 

업데이트할 때마다 추가해주는 방식으로 해결 

    toDos = parsedToDos;

 

 

 



딕셔너리 형식으로 object 별로 id 부여하기  

기존의 string을 object 형식으로 바꾸고 

    const newTodoObj = {
        text : newTodo, 
        id : Date.now(),
    };


이걸 받을 때 그냥 받으면 object로 뜨기 때문에 

    span.innerText = newTodo.text; 

.text를 붙여서 받는다 




array에서 요소를 빼서 각각 함수에 넣어주는 기능 
filter 

[1,2,3,4].filter(xfunction) <= 하나씩 xfuntion에 넣어준다 
여기서 xfunction이 true or false를 리턴하게 만들면 
array에서 빼고 저장시킬 수 있다 

ex ) return item !=3 => 3빼고 [1,2,4] 리턴 


이 기능에 따라 delete 할 때 클릭된 요소라면 그것만 빼 놓고 새로운 array를 만들어주고 
그것을 저장해주면 
지워지면서 + localStorage에서도 지워진다 

function deleteToDo(event){
   const li= event.target.parentElement;
   li.remove();
   toDos = toDos.filter( (toDo) => toDo.id !== parseInt(li.id) ); // 우리가 클릭한 li.did와 다른 toDo는 남겨둠 
   saveToDos();
}



 



지리정보와 웨더정보 받기 

https://openweathermap.org/api => api 받아오는 사이트 => 가입 



지리 정보를 위도와 경도로 간단하게 받기 

function onGeoSuccess(position){
    const lat = position.coords.latitude; 
    const lng = position.coords.longitude;
}


function onGeoError(){
    alert("Can't find you.")
}


navigator.geolocation.getCurrentPosition(onGeoSuccess, onGeoError)      // 좌표 주는 코드 



https://openweathermap.org/current 사이트에서 api call 주소를 가져오면 

기본 로직 

const API_KEY = "xxx";

 

 

 

function onGeoSuccess(position){
    const lat = position.coords.latitude; 
    const lon = position.coords.longitude;
    const url = `https://api.openweathermap.org/data/2.5/weather?lat=${lat}&lon=${lon}&appid=${API_KEY}`
}

url을 들어가면 json 파일로 건네준다 
받아서 요소 뽑기 

    fetch(url).then(response => response.json() ).then(data => {
        console.log(data.name, data.whather[0].main);
    });


이것을 변수로 만들어주고 html에도 span으로 공간 만들어줌 



    fetch(url).then(response => response.json() ).then(data => {
        const name = data.name;
        const wheather = data.whather[0].main;
    });
}




    <div id = "weather"> 
        <span></span>
        <span></span>
    </div>


html로 연동해주는 코드로 다시 수정 

    const weather = document.querySelector("#weather span:first-child")
    const city = document.querySelector("#weather span:last-child")
    city.innerText = data.name;
    weather.innerText = data.whather[0].main;

 

 

 

 

반응형

'Programming > Front-end' 카테고리의 다른 글

리액트 프로젝트 시작하기  (0) 2022.12.29