html/JS에서 event란 사용자가 어느 요소를 클릭하거나 값을 입력하는 등의 행위를 말한다. html상에서 event가 발생할 때 JS가 이를 감지하고 특정 동작을 실행하게 만들 수 있다.
const title = document.querySelector(".hello h1")
function userFuncClick() {
console.log("User clicked .hello <h1>") // click 발생시 작동하고 싶은 함수
}
title.addEventListner("click", userFuncClick) // click을 감지하면 userFuncClick을 실행
위 코드에서 주목할 점은 userFuncClick()
이 아닌 userFuncClick
을 넘겨준다는 점이다. ()
은 함수를 직접 사용하는 것이기 때문에 addEventLinstner
가 함수를 사용하게 만드려면 ()
은 제외하고 넘겨주어야 한다.
만약
userFuncClick()
을 넘긴다면?
click
event와 무관하게 항상 실행되므로 console을 열자마자 함수의 결과가 출력되어있다. 그리고 함수를 클릭하더라도 더 이상 실행되지 않는다.
event 종류에는 뭐가 있지?
console.dir(elementYouGet)
을 하면 우리가 추출한elementYouGet
객체 안의 property가 나온다. 여기에서 앞에on
이 붙은 property가 event이다. 예를 들어onclick
,oncopy
,onmouseleave
등이 있다.
.addEventListener
과.onXX
비교
아래 두 script는 동일하게 동작한다. 다만.addEventListener
을 사용하면 반대로.removeEventListener
을 사용할 수 있기 때문에 이를 더 자주 사용한다.element.addEventListener("click", userFunc); element.onClick = userFunc;
const
와 let
의 사용(NomadCoder JS-3.6 CSS in Javascript 강의의 부가설명입니다.)
const
는 값이 변하지 않는 변수(상수라고 해야 하나), let
은 값이 변하는 변수를 정의할 때 사용한다는 것을 알고 있다. 막상 구분해서 쓸 일이 자주 있을까 싶지만 함수 등을 만들 때 유용하다.
html에서 myVar
이라는 요소를 가져와서 이벤트가 발생할 때 myVar
색깔이 파란색이면 빨간색으로, 빨간색이면 파란색으로 바꾸는 함수를 만든다고 가정해보자.
function ChangeColor(){
if (myVar.style.color === "blue"){
myVar.style.color = "red";
}
else {
myVar.style.color = "blue";
}
}
// .addEventListener은 생략
이제 반복되는 myVar.style.color
을 변수로 선언한다고 해보자.
이 때 if 조건으로 들어가는 color
는 정해진 값을 받아오는 것이므로 변하지 않는다. 따라서 const currentColor = myVar.style.color
로 정의하면 된다.
반대로 if 절 내의 color
는 변동하므로 let
을 사용해야 한다. 그렇다면 위와 동일하게 let newColor = myVar.style.color
로 하면 될까?
// 함수 속에서 변수 선언하기 (잘못된 방법)
function ChangeColor(){
const currentColor = myVar.style.color; // 정해진 값을 받아오므로 const
let newColor = myVar.style.color; // 값이 변동하므로 let?
if (currentColor == "blue"){
newColor = "red";
}
else {
newColor = "blue";
}
}
이렇게 하면 될 것 같지만 막상 코드를 실행해보면 되지 않는다. 그 이유는 newColor
의 값을 바꾼다고 그것이 myVar.style.color
에 적용되지 않기 때문이다.
let newColor = myVar.style.color;
console.log(newColor) // 출력값: blank(myVar 색상이 정해지지 않은 경우)
newColor = "blue";
console.log(newColor); // 출력값: blue
console.log(myVar.style.color); // 출력값: blank
코드에서 등식(=
)은 실제로 둘이 항상 연동되어 같다는 의미가 아니라, 우항에서 좌항으로 값을 건내주는 방식이기 때문에 그런 것이다. 그래서 myVar
의 값을 바꾸면 myVar
의 값만 바뀌는 것이지 myVar.style.color
도 함께 바뀌는 것이 아니다.
코드를 올바르게 고치면 다음과 같다.
// 함수 속에서 변수 선언하기 (옳은 방법)
function ChangeColor(){
const currentColor = myVar.style.color;
let newColor; // 어차피 바꿀거니까 굳이 myVar.style.color을 받아올 필요가 없다
if (currentColor == "blue"){
newColor = "red";
}
else {
newColor = "blue";
}
myVar.style.color = newColor; // 이렇게 해야 newColor의 새로운 값이 myVar에 적용된다.
}
JS로 모든 것을 구현하기보다 html의 기능을 적절히 사용하는 것이 유리하다. 예를 들어 input
변수 입력 여부와 길이를 JS로 확인하면 다음과 같지만
const username = loginInput.value;
if (username==="") {
alert("Please write your name.");
}
else if (username.length > 10){
alert("Your name is too long.");
}
...
}
HTML로는 input
자체에서 required
, maxlength
로 위 조건을 바로 만들 수 있다. (대신 form
을 사용해야 한다.
<form id='login-form'>
<input required maxlength="10" type="text" placeholder="What is your name?" />
<button>Log In</button>
</form>
이렇게 button
까지 form
안에 넣어주면 input
의 변수가 자동으로 전달되기 때문에 JS에서 굳이 button.addEventListener
을 해 줄 필요도 없다.
localStorage
에 저장된 아이디를 삭제해주는 log-out 버튼 만들기NomadCoder JS-4.6 Loading Username 강의에서 localStorage
에 저장된 username이 없으면 로그인 화면을, username이 있으면 'Hello username!'이 나오는 페이지를 만들었다. 여기에 로그아웃 기능을 추가해보았다.
원하는 로그아웃 기능
( 0. usernmae이 없으면 이름을 입력하는 log-in 화면이 나온다. )
1. username이 있을 때 'Hello username!'과 log-out 버튼이 나온다.
2. log-out 버튼을 누르면loclaStorage
에 저장된 username이 사라진다.
3. 그러면 다시 웹페이지를 리부팅해서 처음 단계로 돌아간다.
const loginForm = document.querySelector("#login-form")
const loginInput = document.querySelector("#login-form input");
const logoutForm = document.querySelector("#logout-form"); // log-out form 추가
const greeting = document.querySelector("h1");
const HIDDEN_CLASSNAME = "hidden";
const USERNAME_KEY = "username";
const savedname = localStorage.getItem(USERNAME_KEY);
function onLoginSubmit(event){
event.preventDefault();
loginForm.classList.add(HIDDEN_CLASSNAME);
const username = loginInput.value;
localStorage.setItem(USERNAME_KEY, username);
paintGreeting(username);
}
function paintGreeting(username){
greeting.innerText = `Hello ${username}`;
greeting.classList.remove(HIDDEN_CLASSNAME);
logoutForm.classList.remove(HIDDEN_CLASSNAME); // log-out form이 나오도록 "hidden" 클래스를 삭제한다.
logoutForm.addEventListener("submit", onLogoutSubmit); // log-out form이 submit 되기를 기다린다.
}
function onLogoutSubmit(){
localStorage.removeItem(USERNAME_KEY); // log-out이 submit되면 username을 삭제한다.
location.reload(); // 페이지를 다시 로드해서 처음으로 되돌아간다.
}
if (savedname === null) {
loginForm.classList.remove(HIDDEN_CLASSNAME);
loginForm.addEventListener("submit", onLoginSubmit);
}
else {
paintGreeting(savedname);
}
처음에는 logoutForm.classList.remove(HIDDEN_CLASSNAME);
를 맨 밑의 else
문에 넣었는데 그렇게 하니 if
일 때에는 (즉 저장된 이름이 없어 user가 직접 입력했을 때) log-out 버튼이 안 나오더라. 그래서 painGreeting
함수 안에 넣어서 user가 입력했든 원래 들어있든 'Hello'랑 항상 함께 나오도록 수정했다.
로그아웃이 잘 작동한다!