노마드코더 바닐라 JS로 크롬 앱 만들기 강의를 듣고 정리한 기록입니다. 아래 내용은 4.0 - 4.7 에 해당합니다.
user 에게 질문하고 답변을 받아서 정보를 화면에 표시하는 기능을 만들어 봅니다. js 에는 정보를 기억하는 기능이 있습니다. 우선 html
을 작성합니다.
<div id="login-form">
<input type="text" placeholder="What is your name?" />
<button>Log In</button>
</div>
js
에서 input
과 button
을 불러와 선택합니다.
const loginInput = document.querySelector("#login-form input");
const loginButton = document.querySelector("#login-form button");
button 클릭을 감지하고 작동할 함수를 만들어 보면,
function onLoginBtnClick(){
// 실행할 코드
}
loginButton.addEventListener("click", onLoginBtnClick);
console.dir(input)
이런 식으로 콘솔을 찍어보면 필요한 프로퍼티를 체크할 수 있습니다.
입력받는 username 이 비어있거나, 너무 길면 안되도록 유효성 검사를 한다면, 아래와 같이 조건문을 활용할 수 있습니다.
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")
}
}
loginButton.addEventListener("click", onLoginBtnClick);
사실 input
태그에는 이미 글자수가 15개를 넘어가면 안된다는 기능이 있습니다. 이 기능은 input
태그를 form
태그로 감싸야 적용 가능합니다.
<form id="login-form">
<input
required
maxlength = "15"
type = "text"
placeholder = "What is your name?"
/>
</form>
html
을 위처럼 작성하면 됩니다. 대신 form
대그로 감싸면 입력 후 enter
를 누르거나 button
을 click
하면 submit
이란 이벤트가 발생합니다.
submit
이란 event 를 감지해야 하므로 아래와 같이 코드를 수정합니다.
cosnt loginForm = document.querySelector("#login-form");
const loginInput = document.querySelector("#login-form input");
function onLoginSubmit(){
console.log("hello", loginInput.value);
}
loginForm.addEventListener("submit", onLoginSubmit);
이렇게 하면 form
의 submit
를 인지하고 바로 새로고침 됩니다. 우선 이 기본동작을 멈추어야 합니다
기본 적으로 함수는 ()
괄호가 뒤에 붙어야 실행됩니다.
function
function() // 즉시 실행
loginForm.addEventListener("submit", onLoginSubmit);
// 여기서 두번재 인자, 함수는 () 이 붙지 않아서 바로 실행되지 않음
onLoginSubmit(event);
// event 로부터 받은 정보가 () 안에 들어가서 실행 버튼을 누른다.
기본 동작이 멈추게 하는 함수는 preventDefault() 입니다. 기존 코드를 수정해보면,
const loginForm = document.querySelector("#login-form");
const loginInput = document.querySelector("#login-form input");
function onLoginSubmit(event){
event.preventDefault(); // 기본동작 막기
console.log(loginInput.value);
}
loginForm.addEventListener("submit", onLoginSubmit);
form
의 기본동작은 submit
이었습니다. a
태그로 만든 링크의 기본동작을 확인해 봅니다.
const link = document.querySelector("a");
function handleLinkClick(){
alert("clicked!");
}
link.addEventListener("click", handleLinkClick)
// 이렇게 하면 aler 이 링크의 기본동작을 막고 경고창을 먼저 띄웁니다.
// 경고창을 지우면 그제서야 동작합니다.
발생한 이벤트에 대한 정보는 함수의 인자로, 정보가 담긴 객체 형태로 전달됩니다.
handleLinkClick({info});
아래처럼 console.log
로 event
를 확인해보면,
const link = document.querySelector("a");
function handleLinkClick(event) {
console.log(event);
alert("clicked!");
}
link.addEventListener("click", handleLinkClick)
링크의 클릭은 submitEvent
가 아니라 mouseEvent
라는 것을 알 수 있습니다. screenX
screenY
로 유저가 클릭한 위치 정보도 알 수 있습니다.
const link = document.querySelector("a");
function handleLinkClick(event){
event.preventDefault(); // 이렇게 하면 링크의 기본동작 막는다.
console.dir(event); // event 값 확인
}
link.addEventListener("click", handleLinkClick)
브라우저는 event
에 대한 정보를 담아주고, 우리는 자리를 만들어줍니다.
유저가 이름을 제출하면 form
을 없애고 싶다면, css
를 활용합니다.
.hidden {
display: none;
}
유저가 이름을 제출한 후 form
에 hidden
이란 클래스를 붙여줍니다. 전체 코드를 다시 써보면,
const loginForm = document.querySelector("#login-form");
const loginInput = document.querySelector("#login-form input");
function onLoginSubmit(event){
event.preventDefault(); // 이렇게 하면 링크의 기본동작 막는다.
const username = loginInput.value;
loginForm.classList.add("hidden") // 클래스 추가해서 안보이게
}
loginForm.addEventListener("submit", onLoginSubmit);
이제 html
에 h1
태그를 추가합니다. hidden
클래스를 달아 처음엔 보이지 않게 하고, 텍스트가 입력될 경우 h1
태그에 넣어서 보여주게 하고 form
은 안 보이게 해줍니다.
// html 추가
<h1 id="greeting" class="hidden"></h1>
// js 추가 및 수정
const greeting = document.querySelector("#greeting")
function onLoginSubmit(event){
event.preventDefault(); // 기본 동작 막고
loginForm.classList.add("hidden") // 폼을 안 보이게
const username = loginInput.value; // 사용자 입력값을 변수로
greeting.innerText = "Hello" + username; // h1 태그에 출력하고
greeting.classList.remove("hidden"); // 눈에 보이게 히든을 없애주는
}
hidden
이란 class
이름이 반복되니까 변수로 지정합니다. 일반적으로 스트링만 포함된 변수는 대문자로 표기합니다.
const HIDDEN_CLASSNAME = "hidden";
위 변수를 넣어서 수정하고 표기방식을 약간 바꿔주면,
function onLoginSubmit(event){
event.preventDefault(); // 기본 동작 막고
loginForm.classList.add(HIDDEN_CLASSNAME) // 폼을 안 보이게
const username = loginInput.value; / 사용자 입력값을 변수로
greeting.innerText = `Hello ${username}`; // h1 태그에 출력하고
greeting.classList.remove(HIDDEN_CLASSNAME); // 눈에 보이게 히든을 없애주는
}
// "Hello" + username 는 이렇게 바꿀 수 있다. `Hello ${username}`
유저가 입력한 값을 기억하는 것은 흔한 기능이라 local storage
란 API
가 존재합니다.개발자도구에서 Application
탭 좌측에서 볼 수 있습니다. 유저 정보를 저장하는 다양한 도구가 있는데 Session Stroage
IndexedDB
Web SQL
Cookies
Trust Tokens
개 중에 local storage
가 가장 다루기 쉽습니다.
local storage API
를 살펴보면 다양한 method
들이 있습니다.
localStorage.setItem('myCat', 'Tom')
// 아이템을 저장하는 기능
localStorage.getItem("myCat") // Tom
// 저장한 아이템 불러오기, 해당 key 값으로
localStorage.removeItem("myCat")
// 아이템 지우기
기존 코드에 추가해보면,
function onLoginSubmit(event){
event.preventDefault();
loginForm.classList.add(HIDDEN_CLASSNAME)
const username = loginInput.value;
localStorage.setItem("username", username)
greeting.innerText = `Hello ${username}`;
greeting.classList.remove(HIDDEN_CLASSNAME);
}
loginForm.addEventListener("submit", onLoginSubmit);
아직은 새로고침하고 저장된 username
이 뜨지 않는 상태입니다.
local storage
가 비어있으면 form
을 보여주고 local storage
에 정보가 으면 form
을 보여주지 않고 h1
만 보여줍니다.
먼저 할 일은 local storage
의 유저 정보 유무를 확인하는 것입니다.
localStorage.getItem("username")
// username 이 없으면 null 을 반환
변수를 만드고 조건문 기존 틀을 잡아보면,
const savedUsername = localStorage.getItem("username");
if (savedUsername === null) {
// show the form
} else {
// show the greeting
}
그리고 반복되는 username
은 오타가 날 수 있으면 변수로 고정합니다. string
오타는 js
가 지적하지 않지만 변수명 오타는 찾아서 알려줍니다.
const USERNAME_KEY = "username";
일단 form
도 처음에 보이지 않게 hidden
클래스를 달아주고 위 조건문을 작성해보면,
if (savedUsername === null) {
loginForm.classList.remove(HIDDEN_CLASSNAME);
loginForm.addEventListener("submit", onLoginSubmit);
} else {
greeting.innerText = `Hello ${savedUsername}`;
greeting.classList.remove(HIDDEN_CLASSNAME);
}
이전 코드들과 다 함께 써보면,
const loginForm = document.querySelector("#login-form");
const loginButton = document.querySelector("#login-form button");
const loginInput = document.querySelector("#login-form input");
const greeting = document.querySelector("#greeting");
const HIDDEN_CLASSNAME = "hidden";
const USERNAME_KEY = "username";
function onLoginSubmit(event){
event.preventDefault();
loginForm.classList.add(HIDDEN_CLASSNAME)
const username = loginInput.value;
localStorage.setItem(USERNAME_KEY, username)
greeting.innerText = `Hello ${username}`;
greeting.classList.remove(HIDDEN_CLASSNAME);
}
const savedUsername = localStorage.getItem(USERNAME_KEY);
if (savedUsername === null) {
loginForm.classList.remove(HIDDEN_CLASSNAME);
loginForm.addEventListener("submit", onLoginSubmit);
} else {
greeting.innerText = `Hello ${savedUsername}`;
greeting.classList.remove(HIDDEN_CLASSNAME);
}
중복되는 코드는 아래처럼 함수로 묶어줄 수 있습니다.
function paintGreetings(username) {
greeting.innerText = `Hello ${username}`;
greeting.classList.remove(HIDDEN_CLASSNAME);
}
이렇게 묶어서 다시 써보면,
const loginForm = document.querySelector("#login-form");
const loginButton = document.querySelector("#login-form button");
const loginInput = document.querySelector("#login-form input");
const greeting = document.querySelector("#greeting");
const HIDDEN_CLASSNAME = "hidden";
const USERNAME_KEY = "username";
function onLoginSubmit(event){
event.preventDefault();
loginForm.classList.add(HIDDEN_CLASSNAME)
const username = loginInput.value;
localStorage.setItem(USERNAME_KEY, username)
paintGreetings(username);
}
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);
loginForm.addEventListener("submit", onLoginSubmit);
} else {
paintGreetings(username);
}
함수를 호출하는 위치에 따라 유저 정보는 다른 곳에서 옵니다. local storage
에 유저 정보가 있으면 거기서 정보를 받아서 인자로 넣어주고 없다면 입력되는 정보를 받아서 넣습니다.