코딩을 할 때 효과적인 방식은 html은 html파일에만 쓰고
css는 css파일에만 쓰고 자바스크립트는 로직만 처리하게끔 분리하는것이다.
간단한 예시로 어떻게 자바스크립트가 로직을 처리하며 html과 css를 조작할 수 있는지 알아보자.
다음의 html과 javascript 코드가 있다.
<h1 id="title">This works</h1>
const title = document.querySelector("#title");
여기서 내가 하고싶은건 브라우저에서 클릭이라는 이벤트를 실행할때마다 타이틀의 폰트컬러가 바뀌게 하는 것이다.
이를 실행하기 위해서 필요한건 첫째로 클릭에 대한 새로운 클래스를 선언해주는 거다.
h1 {
color: #fd79a8;
}
.clicked {
color: #a29bfe;
}
const CLICKED_CLASS = "clicked"
각각의 css, javascript파일에 clicked class를 추가해주면 시작할 준비가 된다.
html에 클래스를 직접 입력하지 않고 javascript 로직을 이용해서 필요에 따라 클래스값을 조작하는 방법을 사용할 것이다.
클릭이라는 이벤트를 실행할때마다 색깔이 바뀌는 로직은 이벤트리스너와 조건문을 사용해야한다.
function handleClick(){
const currentClass = title.className;
//class값을 자바스크립트에서 가져오기위해서는 className을 쓴다. class자체가 중요한 표현이라 단독으로 사용못함
if(currentClass !== CLICKED_CLASS){
title.className = CLICKED_CLASS;
} else {
title.className = '';
}
function init(){
addEventListener("click", handleClick);
};
//click이라는 이벤트가 실행될때마다 handleClick함수가 작동한다. 함수 뒤에 ()를 붙이면 이 함수를 당장 실행하라는 의미기때문에 괄호를 쓰지않는다.
inint();
handleClick이라는 함수 안에 currentClass라는 새로운 변수를 만들고 타이틀의 현재 클래스값으로 선언한다.
html에 타이틀 클래스를 지정해놓지 않았기때문에 콘솔에 찍어보면 빈값이 나온다.
여기에 조건문을 만들어 현재 타이틀 클래스값이 clicked가 아니면 clicked로 바꿔주고 같으면 빈 값으로 두게한다.
이 결과 클릭 이벤트마다 html 문서에 title class="clicked"가 나타났다가 사라짐을 반복하게 된다는걸 콘솔에서 확인할 수 있다.
하지만 여기서 문제가 발생하는데,
만약 내가 html title에 새로운 클래스값을 준다면?
<h1 id="title" class="btn"> This works! </h1>
.btn {
cursor: "pointer"
}
타이틀에 새로운 클래스를 주고 커서를 포인터로 바꾸도록했다.
하지만 실행해보면 처음 커서를 댔을때는 포인터로 동작하지만,
클릭 이벤트를 실행하면 포인터가 사라져버린다.
클래스값이 clicked로 바뀌어버렸기 때문이다.
이럴때 문제를 해결하는 방법은 역시 자바스크립트에서 클래스이름을 조작하는것이다. 이때 등장하는 것이 classList이다.
classList를 이용하면 클래스를 조작하는 다양한 메서드들을 쓸 수 있다.
classList.add
: 클래스를 필요에 따라 삽입한다.
classList.remove
: 클래스를 필요에 따라 제거한다.
function handleClick() {
const currentClass = title.className;
if (currentClass !== CLICKED_CLASS) {
title.classList.add(CLICKED_CLASS);
} else {
title.classList.remove(CLICKED_CLASS);
}
}
현재 타이틀 클래스값이 clicked가 아니면 그 값을 클래스에 삽입하고, 맞으면 clicked를 제거하라고 명령한다.
그러면 처음 클릭했을때 타이틀 클래스에 clicked가 추가되지만 다음 동작은 실행되지 않는다.
왜냐면 타이틀 클래스가 btn clicked로 변경되었기 때문이다.
그래서 이 부분도 동시에 해결할 수 있는 방식으로 바꿔야한다.
classList.contains( )
classList.contains
: 값이 존재하는지 체크한다. (true/false)
이 메서드를 사용해서 타이틀 클래스에 값이 존재하는지 확인하고,
없으면 clicked를 삽입하고 있으면 clicked를 제거하는 로직을 만든다. 이방식을 통해 두가지 타이틀 클래스 btn과 clicked가 공존할 수 있다.
function handleClick() {
const hasClass = title.classList.contains(CLICKED_CLASS);
if (!hasClass) {
title.classList.add(CLICKED_CLASS);
} else {
title.classList.remove(CLICKED_CLASS);
}
}
그리고 마지막으로 이 모든걸 한큐에 해결할 수 있는 메서드가 있다.
classList.toggle( )
classList.toggle()
: 클래스값이 있는지 체크하고 없으면 더하고 있으면 제거한다.
function handleClick(){
title.classList.toggle(CLICKED_CLASS);
}
super simple!