동백 // 노마드 코더 바닐라JS: Login

2021. 11. 4. 18:23강의 정리/노마드코더( 바닐라 JS 강의 )

반응형

출처 : https://nomadcoders.co/

 

Input Values

 

핵심 : user에게 질문을 하고, 어떻게 정보들을 받을지에 대해 배운다.

 

 

. HTML에서 모든 것이 시작 되어야 한다. ( element들을 JS로 가져오기 위해서 )

 

 

 

1. HTML에서 input과 button을 생성하고, div id로 묶어준다. ( 이 때 id는 중복되면 안된다! )

 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <!-- css 연결 -->
    <link rel="stylesheet" href="style.css">
    <title>Momentum</title>
</head>
<body>
    <div id="login-form"> 
        <input type="text" placeholder="What is your name?">
        <button>Log In</button>
    </div>  
    <!-- 자바 스크립트 연결 -->
    <script src="app.js"></script>
</body>
</html>

1번 코드 이미지

 

 

 

2. JS에서 HTML element( id = "login-form) 불러오기

// querySelector는 id를 찾는지, class를 찾는지 분명히 해줘야 함 ex) id는 앞에 #붙임. 
const loginForm = document.querySelector("#login-form");

// id나 클래스를 변수에 연결했으면, document가 아닌 바로 변수를 통해서 form을 찾을 수 있음. 
const loginInput = loginForm.querySelector("input");
const loginInput = loginForm.querySelector("button");

 

3. JS에서 button click시 상호작용(event) 만들기.

// querySelector는 id를 찾는지, class를 찾는지 분명히 해줘야 함 ex) id는 앞에 #붙임. 
const loginForm = document.querySelector("#login-form");

// id나 클래스를 변수에 연결했으면, document가 아닌 바로 변수를 통해서 form을 찾을 수 있음. 
const loginInput = loginForm.querySelector("input");
const loginButton = loginForm.querySelector("button");


function onLoginBtnClick() {
    console.log("click");
}


loginButton.addEventListener("click", onLoginBtnClick);

 

4. 입력받은 value를 가져와서 콘솔에 표시하기. 

// querySelector는 id를 찾는지, class를 찾는지 분명히 해줘야 함 ex) id는 앞에 #붙임. 
const loginForm = document.querySelector("#login-form");

// id나 클래스를 변수에 연결했으면, document가 아닌 바로 변수를 통해서 form을 찾을 수 있음. 
const loginInput = loginForm.querySelector("input");
const loginButton = loginForm.querySelector("button");


function onLoginBtnClick() {
    console.dir(loginInput.value); // value는 입력 받은 값을 저장해준다.
}


loginButton.addEventListener("click", onLoginBtnClick);

 

 


 

 

 

Form Submission

 

핵심 : username의 유효성을 검사 할 수있다.

 

 

깨알 Tip // VSC에서 같은 이름의 변수를 다중 선택하려면 ctrl + shift + L을 누르면 된다.

 

1. 입력받은 input이 사용자가 올바르게 입력을 하였는지 검사하기 위해서 HTML에서 form을 사용한다.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <!-- css 연결 -->
    <link rel="stylesheet" href="style.css">
    <title>Momentum</title>
</head>
<body>
    <!--  input의 유효성 검사를 작동시키기 위해서는 항상 form안에 있어야 함.-->
    <form id="login-form"> 
        <input 
            <!-- required는 공백을 방지해주고, maxlength는 최대 길이 설정-->
            required            
            maxlength="15" 
            type="text" 
            placeholder="What is your name?">
        <button>Log In</button>
    </form>  
    <!-- 자바 스크립트 연결 -->
    <script src="app.js"></script>
</body>
</html>

 

 

// JS에서 구현하는 방법 ( 추천 안함 )

function onLoginBtnClick() {
    const username = loginInput.value; // value는 입력받은 것을 저장해준다.
    
    // 만약 사용자가 공백을 입력했다면    
    if(username === ""){
        alert("Please write your name");
    } // 만약 16글자 이상을 입력하였다면 
    else if(username.length > 15){
        alert("Your name is too long");
    }
}    

loginButton.addEventListener("click", onLoginBtnClick);

공백을 입력하였을 때
16글자 이상 입력이 안됌

 

현재까지 문제점 

. 입력하고 버튼을 누르면 새로고침이 실행되서 value가 사라짐

그 이유는 form이 submit되고 있기 때문임.

 

. 우리가 form 안에서 엔터를 누르고, input이 더 존재하지 않는다면 자동으로 submit이 됨.

. 또는 form안에 있는 버튼을 눌렀을 때, 이 때도 form이 자동으로 submit이 됨.

. 즉 우리는 더이상 click에 신경 쓸 필요가 없음. 

. 이제 우리의 관심사는 form의 submit 막는 것임.

 

. 브라우저가 새로고침하지 않고 user 정보를 저장하도록 해야한다.

 

 

 


 

 

 

Events

 

핵심 :  form의 submit이라는 event가 발생하는 것을 막는 것을 배운다.

 

Tip // submit은 엔터를 누르거나 버튼을 클릭할 때 발생함.

 

1. 클릭이 아닌 submit event를 감지한다. 

// querySelector는 id를 찾는지, class를 찾는지 분명히 해줘야 함 ex) id는 앞에 #붙임. 
const loginForm = document.querySelector("#login-form");
const loginForm = document.querySelector("#login-form input");

function onLoginsubmit() {
    const username = loginInput.value; // value는 입력받은 것을 저장해준다.
    // form을 submit 할 때 입력값을 받아냄.
    console.log(username);
}    

// click이 아닌 submit을 감지하기. ( 새로고침을 막기 위해서 )
loginForm.addEventListener("submit", onLoginsubmit);

 

Tip // 새로고침이 일어나는 건 form submit의 기본 동작이다.

 

Tip // 브라우저가 function을 호출할 때 argument로 여러가지 정보들을 준다.

function onLoginsubmit(Argument) {
    Argument.preventDefault(); // 어떤 event의 기본 행동이든지 발생되지 않도록 막는다.
    console.log(Argument);
    }

위와 같이 브라우저가 argument를 통해서 여러 정보를 넘겨준다.

Tip // 링크의 기본 동작은 클릭시 다른 페이지로 이동하는 것이다.

 

Tip // 모든 EventListner function의 첫번째 argument는 항상 방금 실행된 event에 대한 정보가 된다.

 

Tip // addEventListener 안에 있는 함수는 절대 직접 실행하지 않는다. 브라우저가 대신 실행해주기 때문에

 

 

2. JS을 통해 form submit의 기본 동작인 새로고침이 일어나지 않도록 만든다.

 

// querySelector는 id를 찾는지, class를 찾는지 분명히 해줘야 함 ex) id는 앞에 #붙임. 
const loginForm = document.querySelector("#login-form");
const loginInput = document.querySelector("#login-form input");

// 브라우저가 첫번째 function을 호출할 때 argument로 여러가지 정보들을 준다.
function onLoginsubmit(event) {
    // 브라우저가 기본 동작을 실행하지 못하게 막는다.
    event.preventDefault();
    
    // 입력 받은 value를 console 창에 출력한다. 
    console.log(logininput.value);
}    

// click이 아닌 submit을 감지하기. ( 새로고침을 막기 위해서 )
loginForm.addEventListener("submit", onLoginsubmit);

입력 한 value가 console창에 출력된다.

 

 

 

 


 

 

Getting Username

 

핵심 :  Username 입력받고 저장하기

 

1. CSS를 이용해서 유저가 이름을 제출한 후에 로그인 Form을 없애기

// querySelector는 id를 찾는지, class를 찾는지 분명히 해줘야 함 ex) id는 앞에 #붙임. 
const loginForm = document.querySelector("#login-form");
const loginInput = document.querySelector("#login-form input");

// 브라우저가 첫번째 function을 호출할 때 argument로 여러가지 정보들을 준다.
function onLoginsubmit(event) {
    // 브라우저가 기본 동작을 실행하지 못하게 막는다.
    event.preventDefault();
    
    const username = loginInput.value;
    // loginForm의 event가 실행될 때 hidden class 추가
    loginForm.classList.add("hidden");
}    

// click이 아닌 submit을 감지하기. ( 새로고침을 막기 위해서 )
loginForm.addEventListener("submit", onLoginsubmit);

로그인 후 form이 숨겨진 모습

 

2. 로그인 후 form을 숨겨졌으니, 그 자리에 h1을 화면에 표시함.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <!-- css 연결 -->
    <link rel="stylesheet" href="style.css">
    <title>Momentum</title>
</head>
<body>
    <!--  input은 항상 form안에 있어야 함.-->
    <form id="login-form"> 
        <input 
            required            
            maxlength="15" 
            type="text" 
            placeholder="What is your name?">
        <button>Log In</button>
    </form>  
    <!-- form이 사라지고 출력 될 h1-->
    <h1 id="greeting" class="hidden"></h1>
    <!-- 자바 스크립트 연결 -->
    <script src="app.js"></script>
</body>
</html>
// querySelector는 id를 찾는지, class를 찾는지 분명히 해줘야 함 ex) id는 앞에 #붙임. 
const loginForm = document.querySelector("#login-form");
const loginInput = document.querySelector("#login-form input");
const greeting = document.querySelector("#greeting");

// 일반적으로 string만 포함된 변수는 대문자로 표기함.
const HIDDEN_CLASSNAME = "hidden";

// 브라우저가 첫번째 function을 호출할 때 argument로 여러가지 정보들을 준다.
function onLoginsubmit(event) {
    
    // 브라우저가 기본 동작을 실행하지 못하게 막는다.
    event.preventDefault();
    
    const username = loginInput.value;
    
    // loginForm의 event가 실행될 때 hidden class 추가
    loginForm.classList.add(HIDDEN_CLASSNAME);
	
    // form이 사라지고, 그 자리에 Hello + username을 출력하고, 
    // 중복되니 hidden class 삭제
    greeting.innerText = "Hello" + username;
    greeting.classList.remove(HIDDEN_CLASSNAME);
}    

// click이 아닌 submit을 감지하기. ( 새로고침을 막기 위해서 )
loginForm.addEventListener("submit", onLoginsubmit);

 

 greeting.innerText = "Hello " + username;

Tip // 위 코드를 더욱 편리하게 아래 처럼 만들 수 있음. ( 변수를 String 안에 사용할 수 있음 )

greeting.innerText = `Hello ${username}`;

 

 

 

 


 

 

Saving Username

 

핵심 :  Username 저장하기

 

현재까지의 submit시 event 순차적으로 정리하기

 

1. event.preventDefault(); 로 브라우저의 기본 동작을 멈춘다.

 

2. login-form에 "hidden"이라는 class를 추가해줌 // 이 때 login-Form과 greeting 모두 같은 class를 가지고 있다.

 

3. 입력 받은 value를 username 변수에 저장한다.

 

4. 비어있는 h1인 greeting을 가져다가 "hello username"라는 텍스트를 넣어준다.

 

5. greeting의 hidden class를 제거해줌. // 그러면 이제 hidden class명을 가지고 있는 것은 form뿐

 

function onLoginsubmit(event) {
    
    // 브라우저가 기본 동작을 실행하지 못하게 막는다.
    event.preventDefault();
    
    // loginForm의 event가 실행될 때 hidden class 추가
    loginForm.classList.add(HIDDEN_CLASSNAME);
    
    const username = loginInput.value;

    // form이 사라지고, 그 자리에 Hello + username을 출력하고, 
    // 중복되니 hidden class 삭제
    greeting.innerText = `Hello ${username}`;
    greeting.classList.remove(HIDDEN_CLASSNAME);
}

 

 

 

 

1. localStorage를 이용하여, value 저장(기억)하기

ex) 유튜브에서 볼륨을 조절하고 새로고침하면, 유튜브가 그 볼륨값을 기억하고있듯

 

function onLoginsubmit(event) {
    
    // 브라우저가 기본 동작을 실행하지 못하게 막는다.
    event.preventDefault();
    
    // loginForm의 event가 실행될 때 hidden class 추가
    loginForm.classList.add(HIDDEN_CLASSNAME);
    
    const username = loginInput.value;

    // 로컬 저장소에 key값이 "username"인 username을 저장함.
    localStorage.setItem("username",username);

    // form이 사라지고, 그 자리에 Hello + username을 출력하고, 
    // 중복되니 hidden class 삭제
    greeting.innerText = `Hello ${username}`;
    greeting.classList.remove(HIDDEN_CLASSNAME);
}

 

 

 

개발자 도구에서 로컬 스토리지 찾기

 

1. 콘솔창에서 위의 명령어 입력
2. 로컬 스토리지에 저장됨
값을 불러 올 수도 있음.
값을 삭제 할 수있음

 

localStorage.setItem("", "") : 키와 값 불러오기

localStorage.getItem("") : 값 불러오기

localStorage.removeItem("") : 값 삭제하기

 

 

 

 

 


 

 

Loading Username

 

핵심 :  local storage가 비어있으면 form부터 보여준다.( db가 없으면, 로그인 폼을 띄워준다. )

 

 

Tip // local storage에 username이 없으면, null을 반환한다.

 

Tip // 변수나 인자로 같은 string을 반복해서 사용하는 경우에 변수로 고정해준다.

 

Tip // 같은 의미의 코드가 반복되면 함수로 만들어버리자!

 

 

. 만약 유저정보가 local storage에 없으면, 웹사이트는 Login-form을 보여줄 것이고, 

유저 정보가 있으면, Login-form을 감출 것이다. 

 

// querySelector는 id를 찾는지, class를 찾는지 분명히 해줘야 함 ex) id는 앞에 #붙임. 
const loginForm = document.querySelector("#login-form");
const loginInput = document.querySelector("#login-form input");
const greeting = document.querySelector("#greeting");


// 실수(오타)를 만들고 싶지 않은 변수들
// 반복되고, string만 포함된 변수는 대문자로 표기하여 하나로 묶어줌.
const HIDDEN_CLASSNAME = "hidden";
const USERNAME_KEY = "username";


// 브라우저가 첫번째 function을 호출할 때 argument로 여러가지 정보들을 준다.
function onLoginsubmit(event) {
    
    // 브라우저가 기본 동작을 실행하지 못하게 막는다.
    event.preventDefault();
    
    // loginForm의 event가 실행될 때 hidden class 추가
    loginForm.classList.add(HIDDEN_CLASSNAME);
    
    const username = loginInput.value;

    // 로컬 저장소에 key값이 "username"인 username을 저장함.
    localStorage.setItem(USERNAME_KEY,username);

    // form이 사라지고, 그 자리에 Hello + username을 출력하고, 
    // 중복되니 hidden class 삭제
    paintGreetings(username);
}    


// click이 아닌 submit을 감지하기. ( 새로고침을 막기 위해서 )
loginForm.addEventListener("submit", onLoginsubmit);

// 같은 의미의 코드가 반복되면 함수로 만들어버리자!
function paintGreetings(username) {
    greeting.innerText = `Hello ${username}`;
    greeting.classList.remove(HIDDEN_CLASSNAME);
    
}

// local storage에 "username" key값의 데이터를 변수에 저장한다.
const savedUsername = localStorage.getItem(USERNAME_KEY);

// 만약 local storage에 DB가 없다면 form의 hidden을 제거함으로서 form을 보여줘라.
if(savedUsername === null) {
    loginForm.classList.remove(HIDDEN_CLASSNAME);
    loginForm.addEventListener("submit", onLoginsubmit);
} 
// 만약 local storage에 DB가 있다면 greeting의 hidden을 제거함으로서 greeting을 바로 보여준다.
else {
    paintGreetings(savedUsername);
}

 

로컬 저장소가 비어있자 login-form을 보여준다.
로컬 저장소에 값이 있자, greeting을 바로 보여준다.

 

 

 

 

 

 

 

 

 

 


핵심 요약

1. HTML에서 모든 것이 시작 되어야 한다. ( element들을 JS로 가져오기 위해서 )

2. local storage는 정보를 저장하고 불러오고 삭제하는 브라우저가 가지고있는 작은 DB다.

3. local storage는 없는 값을 입력하면, null을 반환한다.

4. 새로고침이 일어나는 건 form submit의 기본 동작이다.

5. 모든 EventListner function의 첫번째 argument는 항상 방금 실행된 event에 대한 정보가 된다.

6. addEventListener 안에 있는 함수는 절대 직접 실행하지 않는다. 브라우저가 대신 실행해주기 때문에

7. 링크의 기본 동작은 클릭시 다른 페이지로 이동하는 것이다.

8. 변수나 인자로 같은 string을 반복해서 사용하는 경우에 변수로 고정해준다.

9. 같은 의미의 코드가 반복되면 함수로 만들어버리자!

 

 

진행 순서

1. 유저가 처음 앱을 열면 form과 h1은 css에 있는 hidden이라는 class 때문에 숨겨져있음

2. JS가 USERNAME_KEY를 가지고 local storage를 확인 함.

2-1. savedUsername 값이 null이라면, form에서 HIDDEN_CLASSNAME을 지워줌

      savedUsername 값이 null이 아니라면, paintGreetings 함수를 호출 해줌.

2-2. 그럼 이제 form이 표시되고, 그 다음에는 addEventListener가 form이 submit되기를(로그인 하기를) 기다리고 있고 submit이 발생하면 JS가 onLoginSubmit 함수를 호출 함.

3. onLoginSubmit  함수는 브라우저의 기본 동작을 막아주고,  form을 숨기기 위해서 다시 hidden class를 추가해줌.

3-1. 그 이후 입력 값을 local storage에 저장하고, paintGreetings 함수 호출

4. paintGreetings 함수는 화면에 h1을 출력해주고, h1을 표시하기 위해 hidden을 제거해줌

 

 

최종 코드

HTML

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <!-- css 연결 -->
    <link rel="stylesheet" href="style.css">
    <title>Momentum</title>
</head>
<body>
    <!--  input은 항상 form안에 있어야 함.-->
    <form class="hidden" id="login-form"> 
        <input 
            required            
            maxlength="15" 
            type="text" 
            placeholder="What is your name?">
        <button>Log In</button>
    </form>  
    <!-- form이 사라지고 출력 될 h1-->
    <h1 id="greeting" class="hidden"></h1>
    <!-- 자바 스크립트 연결 -->
    <script src="app.js"></script>
</body>
</html>

CSS

.hidden {
    display: none;
}

JS

// querySelector는 id를 찾는지, class를 찾는지 분명히 해줘야 함 ex) id는 앞에 #붙임. 
const loginForm = document.querySelector("#login-form");
const loginInput = document.querySelector("#login-form input");
const greeting = document.querySelector("#greeting");


// 실수(오타)를 만들고 싶지 않은 변수들
// 반복되고, string만 포함된 변수는 대문자로 표기하여 하나로 묶어줌.
const HIDDEN_CLASSNAME = "hidden";
const USERNAME_KEY = "username";


// 브라우저가 첫번째 function을 호출할 때 argument로 여러가지 정보들을 준다.
function onLoginsubmit(event) {
    
    // 브라우저가 기본 동작을 실행하지 못하게 막는다.
    event.preventDefault();
    
    // loginForm의 event가 실행될 때 hidden class 추가
    loginForm.classList.add(HIDDEN_CLASSNAME);
    
    const username = loginInput.value;

    // 로컬 저장소에 key값이 "username"인 username을 저장함.
    localStorage.setItem(USERNAME_KEY,username);

    // form이 사라지고, 그 자리에 Hello + username을 출력하고, 
    // 중복되니 hidden class 삭제
    paintGreetings(username);
}    


// click이 아닌 submit을 감지하기. ( 새로고침을 막기 위해서 )
loginForm.addEventListener("submit", onLoginsubmit);

// 같은 의미의 코드가 반복되면 함수로 만들어버리자!
function paintGreetings(username) {
    greeting.innerText = `Hello ${username}`;
    greeting.classList.remove(HIDDEN_CLASSNAME);
    
}

// local storage에 "username" key값의 데이터를 변수에 저장한다.
const savedUsername = localStorage.getItem(USERNAME_KEY);

// 만약 local storage에 DB가 없다면 form의 hidden을 제거함으로서 form을 보여줘라.
if(savedUsername === null) {
    loginForm.classList.remove(HIDDEN_CLASSNAME);
    loginForm.addEventListener("submit", onLoginsubmit);
} 
// 만약 local storage에 DB가 있다면 greeting의 hidden을 제거함으로서 greeting을 바로 보여준다.
else {
    paintGreetings(savedUsername);
}
반응형