이전에 Vanilla JS
를 이용해서 간단한 토이 프로젝트를 해본 경험이 있었는데, 말만 Vanilla JS
지 지금 와서 보면 아주 무식하기 짝이 없는 방식으로 코드를 짰었다....😥
나중에 컴포넌트형으로 리팩토링을 기약하며, 어떤 것이 좋지 못한 방식인지 버튼을 이용한 간단한 예제로 비교를 통해 알아보자.
먼저 버튼을 만들고, 클릭하면 버튼의 배경색을 변경하는 코드를 보자.
const $app = document.querySelector('.app');
const $button = document.createElement('button');
$button.textContent = 'Button';
$app.appendChild($button);
const handleButton = $button => {
if ($button.style.background === '') {
$button.style.background = 'yellow';
} else {
$button.style.background = '';
}
}
$button.addEventListener('click', e => {
handleButton(e.target);
});
const $app = document.querySelector('.app');
const $button1 = document.createElement('button');
$button1.textContent = 'Button 1';
const $button2 = document.createElement('button');
$button2.textContent = 'Button 2';
const $button3 = document.createElement('button');
$button3.textContent = 'Button 3';
$app.appendChild($button1);
$app.appendChild($button2);
$app.appendChild($button3);
const $buttons = document.querySelectorAll('.app button');
const handleButton = $button => {
if ($button.style.background === '') {
$button.style.background = 'yellow';
} else {
$button.style.background = '';
}
}
$buttons.forEach($button => {
$button.addEventListener('click', e => {
handleButton(e.target);
})
})
와우,
동작은 원하는 대로 이루어졌지만, 버튼의 개수가 늘어난 만큼 버튼 생성 및 추가에서 하드 코딩을 하고 있다.
지금이야 간단한 기능만 가지고 있어서 문제가 없지만, 만약 버튼마다 추가되는 이벤트의 종류가 달라지거나 서로 다른 기능이 필요하다면 더더욱 코드가 복잡해질 것이다.
그럼 컴포넌트 방식으로 구현하는 예제를 보자.
버튼을 추상화 시킨 컴포넌트를 통해 명령형에서 구현했던 코드와 동일한 동작을 하도록 만들어보자.
const $app = document.querySelector('.app');
function ButtonComponent({ $target, text }) {
if (!new.target) {
return new ButtonComponent({ $target, text });
}
const $button = document.createElement('button');
$target.appendChild($button);
this.state = {
toggled: false
}
this.setState = nextState => {
this.state = nextState;
this.render();
}
this.handleButton = () => {
this.setState({
toggled: !this.state.toggled
})
}
this.render = () => {
$button.textContent = text;
$button.style.background = this.state.toggled ? 'yellow' : '';
}
$button.addEventListener('click', this.handleButton);
this.render();
}
new ButtonComponent({ $target: $app, text: 'button1'});
new ButtonComponent({ $target: $app, text: 'button2'});
new ButtonComponent({ $target: $app, text: 'button3'});
이 코드도 아직 고칠 점이 많지만, 위에서 명령형으로 구현한 코드와 동일한 동작을 한다.
이렇게 컴포넌트 방식으로 구현하면 확장이 쉬워지고, 읽기도 쉬울뿐더러 재사용하기에도 훨씬 편리하다.