이벤트위임과 데이터속성

박찬욱·2023년 5월 31일
0

Basic JavaScript

목록 보기
6/13
post-thumbnail

개선점

  • 이벤트 위임을 활용해서 코드를 개선할 수 있다.
  • 현재 코드는 버튼을 클릭하거나 엔터키를 입력하면 아이템을 추가한다. 아이템을 추가하는 코드가 중복되어 사용되기 때문에 form 을 이용해서 개선할 수 있다.

🛠️ 리팩토링

<form>
	<input type="text" />
	<button type="submit">
		<i class="fas fa-plus-circle"></i>
	</button>
</form>
// main.js
import { makeItem } from "./action.js";

const itemList = document.querySelector("ul");
const addBtn = document.querySelector("button");
const itemInput = document.querySelector("input");
const form = document.querySelector("form");

form.addEventListener("submit", (e) => {
  try {
    e.preventDefault();
    const item = makeItem(itemList, itemInput);
    itemList.appendChild(item);
    itemInput.value = "";
  } catch (error) {
    console.log("아이템이 중복되어 리스트에 담을 수 없습니다😱");
  }
});

itemList.addEventListener("click", (e) => {
  const id = e.target.dataset.id;
  const nodeName = e.target.nodeName;
  if (id && nodeName === "I") {
    const deleteItem = document.querySelector(`li[data-id="${id}"]`);
    deleteItem.remove();
  }
});

우선 HTML 코드에 form 태그를 추가하였다. form 태그를 활용하면 엔터키를 입력하는 이벤트 핸들러와 버튼을 클릭하는 이벤트 핸들러를 각각 등록하지 않고 submit 이벤트를 이용해서 이벤트 핸들러를 하나만 등록할 수 있다.
앞전에 설명한 것처럼 submit 이벤트는 기본적으로 발생 시, 페이지를 새로 로딩하기 때문에 preventDefault 메서드를 사용했다.
그리고 이전에는 자식 요소인 deleteBtn 에 이벤트 핸들러를 등록해서 아이템을 삭제할 수 있게끔 구현했지만 이벤트 위임 을 활용해서 부모 노드인 itemList 에 이벤트 핸들러를 등록하여 휴지통 아이콘을 클릭했을 때, 즉 자식 노드에 발생하는 이벤트를 부모 노드에서 처리할 수 있게끔 구현하였다.

여기서 data-XXX 라는 데이터 속성 을 활용하였다. 잠깐 짚고 넘어가자.


🤔 데이터 속성이란 ?

데이터 속성은 HTML 요소의 data- 로 시작하는 속성이다. 이러한 데이터 속성의 목적은 특정한 데이터를 DOM 요소에 저장해두기 위함이다. 개발자는 요소에 특정한 데이터를 저장하고 싶은 경우 자유롭게 사용할 수 있다.

// action.js
let id = 0;

export const makeItem = (itemList, itemInput) => {
  itemInput.focus();
  if (!itemInput.value) {
    alert("아이템을 입력해주세요!");
  } else {
    if (checkDuplicate(itemInput.value, itemList)) {
      alert("이미 추가되었습니다!");
    } else {
      const li = document.createElement("li");
      li.setAttribute("data-id", id);
      li.innerHTML = `
          <h4>${itemInput.value}</h4>
          <i class="fas fa-trash" data-id=${id}></i>
      `;
      id++;
      return li;
    }
  }
};

export const checkDuplicate = (value, itemList) => {
  return Array.from(itemList.childNodes).some((li) => value === li.innerText);
};

아이템을 생성해주는 기능을 담당하는 코드이다. 코드를 보면 data-id 라는 데이터 속성을 사용한 것이 보인다.
데이터 속성을 사용한 이유는 각각의 아이템들을 고유의 값은 data-id 로 분류할 수 있고, 이것을 DOM 요소로 개발자의 의도에 맞게 조작할 수 있기 때문이다.
또한 부모 노드인 itemList 에서 발생하는 모든 이벤트들 중에 휴지통 아이콘이 클릭되었을 경우에만 아이템을 지워주기 위해서 휴지콘 아이콘에 데이터 속성을 부여하였다.

데이터 속성은 DOM 객체의 dataset 속성을 참조해서 확인할 수 있다.
main.js 코드에서 e.target.dataset.id 를 통해 내가 지정한 데이터 속성 값인 data-id 에 접근하는 것을 확인할 수 있다. 따라서 data-id 를 지정한 노드 요소이면서 노드의 이름이 I, 즉 아이콘이면 data-id 를 속성으로 갖는 li 요소를 선택자로 지정하여 remove 메서드로 요소를 삭제한다.


🌟 느낀점

이벤트 리스너를 두 번 중복해서 등록하는 것에 찝찝함을 느꼈었는데 form 태그를 활용해 이를 해결할 수 있어서 좋았다. 그리고 자식 노드에 일일히 이벤트를 등록하는 것이 아니라 부모 노드에서 자식 노드의 이벤트를 처리할 수 있으면 처리하게끔 로직을 구성하는 것이 조금 더 우아하게 코드를 짤 수 있겠다는 생각이 들었다.

profile
대체불가능한 사람이다

0개의 댓글