최종 결과물
Counter
0
HTML
<!DOCTYPE html>
<html lang="kr">
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>38JS - Counter</title>
<script src="./counter.js"></script>
<link rel="stylesheet" href="./reset.css">
<link rel="stylesheet" href="./style.css">
</head>
<body>
<div class="container">
<h1 class="">Counter</h1>
<p class="counter_number">0</p>
<div class="btn-container">
<button class="btn decrease" type="button">decrease</button>
<button class="btn reset" type="button">reset</button>
<button class="btn increase" type="button">increase</button>
</div>
</div>
<script>
const counter = new Counter('.container');
</script>
</body>
</html>
CSS
body {
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 100vh;
background: #222;
}
.container {
width: 450px;
}
.container h1 {
color: #fff;
font-size: 24px;
text-align: center;
margin-bottom: 20px;
}
.container .counter_number {
font-size: 42px;
color: #fff;
text-align: center;
margin-bottom: 20px;
}
.container .btn-container {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
max-width: 320px;
margin: 0 auto;
}
.container .btn-container .btn {
border: 1px solid #ddd;
background: transparent;
color: #fff;
padding: 10px 20px;
width: 100px;
cursor: pointer;
}
.container .btn-container .btn:hover {
background: #ddd;
color: #222;
}
.container .btn-container .btn:active {
transform: scale(0.95);
}
.container .btn-container .btn:focus {
outline: none;
}
JS
constructor(target)
- 인자로 클래스명을 받아
document
에서 해당 클래스를 찾아 this.target에 할당 this.count = 0;
으로 초기 카운트값 0으로 지정this.init()
매서드 실행
init()
- this.target에 할당된 DOM 내부에 있는 decrease, increase, reset 클래스를 찾아 각 버튼으로 변수 지정
- 지정된 버튼 변수들에 이벤트 리스너로 각각 액션 할당
increment(), decrement()
this.count
를 각각 1씩 증감this.render()
실행
reset()
this.count
를 0으로 초기화this.render()
실행
render()
this.target
으로 지정된 DOM 내부의.counter_number
클래스를 찾아 텍스트를this.count
로 변경this.count
의 값이 0이면#fff
, 양수면b2e7d5
, 음수면 ``으로 텍스트 컬러 변경
class Counter {
constructor(target) {
this.target = document.querySelector(target);
this.count = 0;
this.init();
}
init() {
const decreaseBtn = this.target.querySelector('.decrease');
const increaseBtn = this.target.querySelector('.increase');
const resetBtn = this.target.querySelector('.reset');
decreaseBtn.addEventListener('click', () => this.decrement());
increaseBtn.addEventListener('click', () => this.increment());
resetBtn.addEventListener('click', () => this.reset());
}
increment() {
this.count++;
this.render();
}
decrement() {
this.count--;
this.render();
}
reset() {
this.count = 0;
this.render();
}
render() {
this.target.querySelector('.counter_number').textContent = this.count;
if(this.count === 0){
counterNumber.style.color = '#fff';
}else if(this.count > 0){
counterNumber.style.color = '#b2e7d5';
}else if(this.count < 0){
counterNumber.style.color = '#c93232';
};
}
}
JS 리팩토링
주요 변경 사항
- init 메서드 내에서 각 버튼 요소를 선택하고 forEach를 사용하여 각 버튼에 대한 이벤트 리스너를 추가
- updateCount 메서드로 버튼의 data-action에 따라 버튼의 동작을 식별
- render 메서드 내에서 카운터 숫자를 업데이트하는 부분을 분리하여 가독성을 향상
굳이 많은 기능을 추가할 예정이 아니므로, 버튼에 data-action 속성을 추가하여
`increment, decrement, reset` 메서드 대신 `updateCounter()` 메서드로 통일하였다.
class Counter {
constructor(target) {
this.target = document.querySelector(target);
this.count = 0;
this.init();
}
init() {
const buttons = this.target.querySelectorAll('button');
buttons.forEach(button => {
button.addEventListener('click', () => {
const action = button.dataset.action;
this.updateCount(action);
});
});
}
updateCount(action) {
if (action === 'increase') {
this.count++;
} else if (action === 'decrease') {
this.count--;
} else if (action === 'reset') {
this.count = 0;
}
this.render();
}
render() {
const counterNumber = this.target.querySelector('.counter_number');
counterNumber.textContent = this.count;
if(this.count === 0){
counterNumber.style.color = '#fff';
}else if(this.count > 0){
counterNumber.style.color = '#b2e7d5';
}else if(this.count < 0){
counterNumber.style.color = '#c93232';
};
}
}