본문 바로가기
개발 공부 일지/JavaScript

이벤트 핸들러를 할당하는 시점

by yelimu 2025. 2. 7.
 
Do it! 웹 프로그래밍을 위한 자바스크립트 기본 편
무엇이든 처음 공부할 때는 기본기부터 빠르게 정복해야 한다. 그래야 그 분야에 재미를 느끼며 빠르게 적응할 수 있다. 《Do it! 웹 프로그래밍을 위한 자바스크립트 기본 편》은 자바스크립트를 통해 웹 프로그래밍에 입문하는 사람들이 가장 먼저 배워야 할 기본 문법을 웹 분야 베스트셀러 저자인 고경희 선생이 모아 엮은 책이다. 137개 예제를 통해 직접 프로그램을 만들면서 기본 문법을 흥미롭게 배운 뒤 ‘1분 복습’, ‘마무리 실습’, ‘연습 문제’ 등
저자
고경희
출판
이지스퍼블리싱
출판일
2019.03.26

여기에서 작성했던 프로그램을 다시 한번 작성해 보았다.

 

X 버튼을 눌러도 아이템이 삭제되지 않는 문제가 발생했다.

 

전체 코드를 보면 크게 세 가지 동작을 하고 있다. 

1. 입력값 가져와서 배열에 저장하기

2. 배열에 있는 값을 화면에 보여주기

3. X 버튼으로 아이템 삭제하기 

 

⚠️한번 어디가 잘못됐는지 찾아보시라 ~ 

// 입력값 가져와서 배열에 저장하기
let itemList = [];

function addList() {
  const input = document.querySelector("#item");
  value = input.value;
  if (value) {
    itemList.push(value);
    input.value = "";
    input.focus();
  }
  showList();
}
const button = document.querySelector("#add");
button.addEventListener("click", addList);

// 배열에 있는 값 화면에 보여주기
function showList() {
  let list = "<ul>";
  for (let i = 0; i < itemList.length; i++) {
    list += "<li>" + itemList[i] + "<span id=" + i + " class='close'>X</span></li>";
  }
  list += "</ul>";
  const listDiv = document.querySelector("#itemList");
  listDiv.innerHTML = list;

} 
const removeBtns = document.querySelectorAll(".close");
for (btn of removeBtns) {
  btn.addEventListener("click", removeList);
}

// 삭제하는 함수
function removeList() {
  // 이벤트가 발생한 요소의 id 속성값 가져옴
  const id = Number(this.getAttribute("id"));
  itemList = itemList.filter((_, i) => i !== id);
  showList();
}

 

 

아무리 생각해도 난 잘 작성한 거 같은데! 싶었지만 

// 배열에 있는 값 화면에 보여주기
function showList() {
  let list = "<ul>";
  for (let i = 0; i < itemList.length; i++) {
    list += "<li>" + itemList[i] + "<span id=" + i + " class='close'>X</span></li>";
  }
  list += "</ul>";
  const listDiv = document.querySelector("#itemList");
  listDiv.innerHTML = list;

  // ⚠️ showList 함수 안에서 이벤트 핸들러가 등록되어야 한다.
  const removeBtns = document.querySelectorAll(".close");
  for (btn of removeBtns) {
    btn.addEventListener("click", removeList);
  }
}

삭제 버튼들에게 이벤트 리스너를 할당해 주는 이 코드가 바로 이 showList 함수 안에서 이루어져야 한다는 점이다.

 

앞에서 본 코드에서는

⚠️ class="close"인 요소를 배열로 반환하는 querySelectorAll 함수가 초기 로드 시점에만 실행되기 때문에

이후에 추가된 span에 대해서는 이벤트 핸들러가 등록되지 않게 된다.

따라서 삭제 버튼을 클릭해도 아-무 일도 생기지 않는다

❗때문에 입력값을 받아 화면에 요소를 생성할 때마다 삭제 이벤트 핸들러를 할당해줘야 하는 것!

즉 showList 함수 안에서 핸들러 할당이 이루어져야한다. 

 

🔈추가로,

add 동작이던, remove 동작이던 배열을 변화시키기 때문에 showList 함수를 호출해야 새로운 배열로 화면이 갱신된다.