문벅스 JS. Step 1 코드 분석 및 요약

Pelixhoon·2022년 11월 12일
1

Dev.

목록 보기
1/4
post-thumbnail
  • 본 글은 Udemy "블랙커피 Vanilla JS Lv1. 문벅스 카페 메뉴 앱 만들기"를 수강하고, 개인적으로 복습하는 차원에서 작성한 글입니다.

  • 저작권 문제가 있을시, 비공개 전환 또는 삭제하겠습니다.

자바스크립트에 대한 베이스가 부족한 상태에서, 리액트를 공부하다 보니 한계가 뚜렷한 느낌이 들어서 공부하게 된 강의!

카페 메뉴판에 메뉴를 추가, 수정, 삭제 기능을 구현하는 것이 Step1의 주요 목표!

1. 메뉴 추가

  $("#espresso-menu-form").addEventListener("submit", (e) => {
    e.preventDefault();
  });

  // 메뉴명을 입력해주는 함수
  const addMenuName = () => {
    if ($("#espresso-menu-name").value === "") {
      alert("값을 입력해주세요");
      return;
    }
    const espressoMenuName = $("#espresso-menu-name").value;
    const menuItemTemplate = (espressoMenuName) => {
      return `
            <li class="menu-list-item d-flex items-center py-2">
                <span class="w-100 pl-2 menu-name">${espressoMenuName}</span>
                <button
                    type="button"
                    class="bg-gray-50 text-gray-500 text-sm mr-1 menu-edit-button"
                >
                    수정
                </button>
                <button
                    type="button"
                    class="bg-gray-50 text-gray-500 text-sm menu-remove-button"
                >
                    삭제
                </button>
            </li>`;
    };

addMenuName이라는 함수를 살펴보면,
espresso-menu-name이라는 id를 가진 input 태그의 value를 가져오고 이를 이용해 기능을 구현한 것을 알 수 있다.

value 값이 없으면 alert를 띄워 값을 다시 입력받고,
값이 있으면 li 태그 안에 espressoMenuName이라는 변수로 넣어 리턴한다.

Event.preventDefault 함수
preventDefault() 메서드는 어떤 이벤트를 명시적으로 처리하지 않은 경우, 해당 이벤트에 대한 사용자 에이전트의 기본 동작을 실행하지 않도록 지정합니다.

preventDefault가 쓰이는 주로 경우

  1. a 태그를 눌렀지만, href 링크로 이동하지 않게 할 경우
  2. form 안에 submit 역할을 하는 버튼을 눌러도 새로 실행하지 않게 하고싶을 경우 (submit은 작동됨)

-> submit을 하게되면, 새로고침이 실행되는 데 이를 막아주는 역할을 하고 있음!


2. 메뉴 개수 카운팅 / 업데이트, 아래로 정렬

  // const 변수 = li 갯수를 카운팅해서 저장해줌
  const UpdateMenuCount = () => {
    const menuCount = $("#espresso-menu-list").querySelectorAll("li").length;
    $(".menu-count").innerText = `${menuCount}`;
  };

  $("#espresso-menu-list").insertAdjacentHTML(
      "beforeEnd",
      menuItemTemplate(espressoMenuName)
    ); // innerHTML을 사용하면 계속해서 덮어써짐. insertAdjacentHTML을 사용해야

  UpdateMenuCount();
  $("#espresso-menu-name").value = "";

UpdateMenuCount 라는 함수를 살펴보면,
espresso-menu-list 라는 ul 태그 안에 li 태그의 갯수를 세는 방식으로 메뉴의 총 갯수를 세고 있는 것을 알 수 있다.

insertHTML 대신 innerAdjacentHTML을 사용했는데,

innerAdjacentHTML
HTML 같은 특정 텍스트를 파싱하고, DOM tree 안 특정 위치에 원하는 노드들을 추가한다. element.insertAdjacentHTML(position, text); 형태로 사용한다.

position의 종류
'beforebegin' : element 앞에
'afterbegin' : element 안에 가장 첫번째 child
'beforeend': element 안에 가장 마지막 child
'afterend': element 뒤에

여기서는 'beforeEnd'를 사용해서 새로 추가되는 메뉴들이 아래로 추가된다.


3. 메뉴 수정 및 삭제

  $("#espresso-menu-list").addEventListener("click", (e) => {
    if (e.target.classList.contains("menu-edit-button")) {
      const $menuName = e.target.closest("li").querySelector(".menu-name");
      const updatedMenuName = prompt(
        "메뉴명을 수정하세요",
        $menuName.innerText
      );
      $menuName.innerText = updatedMenuName;
    }

    if (e.target.classList.contains("menu-remove-button")) {
      if (confirm("정말 삭제하시겠습니까?")) {
        e.target.closest("li").remove();
        UpdateMenuCount();
      }
    }

메뉴 수정 기능부터 살펴보면,
target이 반환하는 classList 안에 menu-edit-button이라는 클래스가 존재하면 메뉴 수정 기능을 실현하게 된다.

e.target.closest("li")를 실행하면 target과 가장 가까운 li 태그를 가져오게 된다.

menu-name이라는 클래스는 span 태그 안에 존재하는데, 수정하고 싶은 값을 prompt로 입력받고 이를 innerText 메소드를 이용해 이를 수정하게 된다.

$menuName.innerText 를 prompt 함수 안에 사용해줌으로써 기존의 수정하려고 했던 메뉴 이름을 prompt의 초기값으로 띄워준다.

[JavaScript] innerHTML, innerText, textContent 차이

에 대해서는 이 글을 참고하자!


참고를 위한 전체코드

const $ = (selector) => document.querySelector(selector);

function App() {
  // Menu 총 갯수를 업데이트해주는 함수
  const UpdateMenuCount = () => {
    const menuCount = $("#espresso-menu-list").querySelectorAll("li").length;
    $(".menu-count").innerText = `${menuCount}`;
  };

  //메뉴명 수정 및 삭제
  $("#espresso-menu-list").addEventListener("click", (e) => {
    if (e.target.classList.contains("menu-edit-button")) {
      const $menuName = e.target.closest("li").querySelector(".menu-name");
      const updatedMenuName = prompt(
        "메뉴명을 수정하세요",
        $menuName.innerText
      );
      $menuName.innerText = updatedMenuName;
    }

    if (e.target.classList.contains("menu-remove-button")) {
      if (confirm("정말 삭제하시겠습니까?")) {
        e.target.closest("li").remove();
        UpdateMenuCount();
      }
    }
  });

  // form태그가 자동으로 전송되는 것을 막아준다.
  $("#espresso-menu-form").addEventListener("submit", (e) => {
    e.preventDefault();
  });

  // 메뉴명을 입력해주는 함수
  const addMenuName = () => {
    if ($("#espresso-menu-name").value === "") {
      alert("값을 입력해주세요");
      return;
    }
    const espressoMenuName = $("#espresso-menu-name").value;
    const menuItemTemplate = (espressoMenuName) => {
      return `
            <li class="menu-list-item d-flex items-center py-2">
                <span class="w-100 pl-2 menu-name">${espressoMenuName}</span>
                <button
                    type="button"
                    class="bg-gray-50 text-gray-500 text-sm mr-1 menu-edit-button"
                >
                    수정
                </button>
                <button
                    type="button"
                    class="bg-gray-50 text-gray-500 text-sm menu-remove-button"
                >
                    삭제
                </button>
                </li>`;
    };

    // 메뉴명이 아래로 쭉 정렬되게 해줌
    $("#espresso-menu-list").insertAdjacentHTML(
      "beforeEnd",
      menuItemTemplate(espressoMenuName)
    ); // innerHTML을 사용하면 계속해서 덮어써짐. insertAdjacentHTML을 사용해야

    // const 변수 = li 갯수를 카운팅해서 저장해줌
    UpdateMenuCount();
    $("#espresso-menu-name").value = "";
  };

  $("#espresso-menu-submit-button").addEventListener("click", () => {
    addMenuName();
  });

  // 메뉴의 이름을 입력받는건 엔터키만!
  $("#espresso-menu-name").addEventListener("keypress", (e) => {
    if (e.key !== "Enter") {
      return;
    }
    addMenuName();
  });
}

App();
  • 리팩토링을 하기 전의 원본 코드입니다.

  • 수정할 내용이나, 지식의 수준이 변화하면 업데이트하겠습니다.

profile
Korea Univ. CSE.

0개의 댓글