N

(TIL)JS로 토글 버튼 만들기 본문

TIL

(TIL)JS로 토글 버튼 만들기

naeunchan 2021. 8. 18. 11:11
728x90
반응형

JavaScript로 토글 버튼을 만들도록 한다.

버튼의 기능은 버튼을 눌렀을 때 버튼 안에 있는 텍스트에 취소선이 그려지거나 없어지는 기능이다.

 

우선 index.html 파일을 만들어 ToggleButton.js 파일을 불러오도록 한다.

또한, 명령형 프로그래밍 방식으로 먼저 만들어본다.

<!DOCTYPE html>
<html lang="en">
  <head>
    <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>Document</title>
  </head>
  <body>
    <script src="./ToggleButton.js"></script>
  </body>
</html>
const body = document.querySelector("body");
const button1 = document.createElement("button");
const button2 = document.createElement("button");
const button3 = document.createElement("button");


button1.textContent = "Button1";
button1.className = "button1";

button2.textContent = "Button2";
button2.className = "button2";

button3.textContent = "Button3";
button3.className = "button3";

body.appendChild(button1);
body.appendChild(button2);
body.appendChild(button3);

// 명령형
button1.addEventListener("click", () => {
  if (button1.style.textDecoration === "line-through") {
    button1.style.textDecoration = "none";
  } else {
    button1.style.textDecoration = "line-through";
  }
});

button2.addEventListener("click", () => {
  if (button2.style.textDecoration === "line-through") {
    button2.style.textDecoration = "none";
  } else {
    button2.style.textDecoration = "line-through";
  }
});

button3.addEventListener("click", () => {
  if (button3.style.textDecoration === "line-through") {
    button3.style.textDecoration = "none";
  } else {
    button3.style.textDecoration = "line-through";
  }
});

 

한 눈에 봤을 때 깔끔하지는 않아도 어떠한 기능을 하는지 알 수는 있다.

그럼 이 코드를 선언형으로 바꾸게 된다면??

const body = document.querySelector("body");
const button1 = document.createElement("button");
const button2 = document.createElement("button");
const button3 = document.createElement("button");

button1.textContent = "Button1";
button1.className = "button1";

button2.textContent = "Button2";
button2.className = "button2";

button3.textContent = "Button3";
button3.className = "button3";

body.appendChild(button1);
body.appendChild(button2);
body.appendChild(button3);

// 선언형
document.querySelectorAll("button").forEach((button) => {
  button.addEventListener("click", (e) => {
    const { target } = e;

    if (target.style.textDecoration === "line-through") {
      target.style.textDecoration = "none";
    } else {
      target.style.textDecoration = "line-through";
    }
  });
});

명령형보다 훨씬 깔끔하게 정리가 되었다.

화면에 있는 모든 버튼은 취소선 기능을 가지고 있기 때문에 한꺼번에 불러와 클릭 이벤트를 연결(?)했다.

 

명령형 프로그래밍은 컴퓨터가 수행할 명령들을 순서대로 써 놓은 것으로, '어떻게 구현하는가'를 중점에 두고 있다.

 

이에 반해 선언형 프로그래밍은 '무엇과 같은지'를 설명하는 데에 중점이 있다. 가장 큰 예시가 HTML와 SQL로 내부적으로 어떻게 동작하는지는 관심이 없고 '이것은 이것을 나타낸다' 정도로만 보여준다. 물론 개발자는 해당 메소드나 함수의 의미나 사용법을 알아야 하지만, 보다 간결하고 정확한 포인트만 보여줄 수 있다는 데 큰 장점이 있다.

 

선언형으로 프로그래밍했기 때문에 버튼을 추상화할 수도 있다.

// html의 body 태그
const body = document.querySelector("body");

function ToggleButton({ target, text }) {
  const button = document.createElement("button");
  target.appendChild(button);

  this.state = {
    toggled: false,
  };

  this.setState = (nextState) => {
    this.state = nextState;
    this.render();
  };

  this.render = () => {
    button.textContent = text;
    button.style.textDecoration = this.state.toggled ? "line-through" : "none";
  };

  button.addEventListener("click", () => {
    this.setState({
      toggled: !this.state.toggled,
    });
  });

  this.render();
}

const button1 = new ToggleButton({
  target: body,
  text: "Button1",
});

const button2 = new ToggleButton({
  target: body,
  text: "Button2",
});

const button3 = new ToggleButton({
  target: body,
  text: "Button3",
});

이처럼 추상화를 통해 각 버튼을 어디에(어떤 태그에) 추가할지, 버튼의 텍스트는 뭘로 할지를 정할 수 있다.

또한, 버튼이 눌렸을 때 각종 버그를 방지하기 위해 독립적으로 상태를 관리하면 보다 질 좋은 프로그래밍을 할 수 있다.

 

 

728x90
반응형

'TIL' 카테고리의 다른 글

(TIL Study)Promise  (0) 2021.08.26
(TIL) 21/08/20 회고록  (0) 2021.08.20
(TIL)JS의 this  (4) 2021.08.17
(TIL Study)동기 처리와 비동기 처리  (1) 2021.08.16
(TIL Day06-3)이터러블과 이터레이터  (0) 2021.08.09