Today I learn... "Array Method 응용하기"

mr.ginger·2021년 5월 20일
0

오늘 있었던 Array Method의 응용에 대해 포스팅을 해보려 한다.

어떤 문제를 해결하였는가?

우선, 오늘 막혔던 부분은 검색창의 구현이었는데, 임의의 ID를 담고 있는 배열을 가지고 있을때, input창에서 입력된 문자를 포함 하고 있는 ID를 표시하는 기능이었다.

조건은 for문을 사용하지 않고, Array, 배열 관련의 메서드를 사용하는 것이었고, 이때 사용 된 키워드는

  • filter
  • forEach
  • from
  • include

였다.

어떻게 문제를 해결하였나?

코드를 가져와 하나씩 설명하자면,

function checkInput() {
  searchInput.addEventListener("keyup", isCurrectId);
}

function init() {
  checkInput();
}

init();

첫번째로 input창에서의 키 입력을 keyup 이벤트를 통해 입력 받는다.

const isCurrectId = (event) => {
  deleteId();
  const toCheckId = event.target.value;
  const checkedId = checkArry.filter((el) => {
    return toCheckId !== "" ? el.includes(toCheckId) : false;
  });
  if (checkedId.length > 0) {
    checkedId.forEach((id) => {
      paintId(id);
    });
  } else {
    deleteId();
  }
};

다음, 입력받은 event에 event.target.value로 접근,
filter와 include를 사용해서 가지고 있는 배열중 입력 받은 문자가 존재하는지 확인하고, 만약 없다면 false, 있다면 filter를 통해 배열로 전달 받는다.

const paintId = (text) => {
  const searchedList = document.createElement("div");
  const searchedName = document.createElement("li");
  const searchedAvatar = document.createElement("img");
  searchedAvatar.src = `/images/avatar/${text}.jpg`;
  searchedName.innerText = text;
  if (text) {
    searchedList.classList.add("searched-list");
    searchedName.classList.add("searched-name");
    searchedAvatar.classList.add("searched-avatar");
    searchedList.appendChild(searchedAvatar);
    searchedList.appendChild(searchedName);
    searchBox.classList.add("showing");
    searchBox.appendChild(searchedList);
  }
};

그 후, if문을 통해 배열에 값이 존재한다면 forEach를 이용, 각각의 배열 아이템으로 변환하여 paintId로 이동시킨다. paintId에서 html 요소들을 그려내고, 배열에 아무 아이템이 없다면 delete로 이동하여 paint로 생성 되었던 요소를 지운다.

const deleteId = () => {
  const searchedList = document.getElementsByClassName("searched-list");
  Array.from(searchedList).forEach((list) => {
    searchBox.removeChild(list);
  });
  searchBox.classList.remove("showing");
};

delete는 getElementsByClassName으로 해당 클래스의 모든 요소를 전달 받지만, 전달 된 요소는 html collection이라서 바로 removeChild를 사용 할 수 없다.

이때 Array.from을 사용해서 유사배열로 바꿔준 다음, forEach를 통해 하나씩 아이템을 모두 없앤다.

이때, isCurrectId의 처음 시작부분에 delete를 사용한 이유는, keyup 이벤트가 일어날때마다 생성 되어있던 html 요소를 삭제해서 초기화 하기 위해 사용하였다.

어떤 부분이 문제였나?

가장 길게 고민했던 부분은, html을 생성 할 수는 있었지만, 삭제를 어느 타이밍에, 어떻게 할지에 대한 고민이었다.

그러던중, isCurrectId 부분에서

const isCurrectId = (event) => {
  deleteId();
  const toCheckId = event.target.value;
  const checkedId = checkArry.filter((el) => {
    return toCheckId !== "" ? el.includes(toCheckId) : false;
  });
  if (checkedId) {
    checkedId.forEach((id) => {
      paintId(id);
    });
  } else {
    //deleteId();
  }
};

과 같이 if문에서 checkedId에서 문제가 발견 되었는데, checkedId에서 배열이 입력 되면서 빈 배열이 들어올 경우도 마찬가지로 true가 출력 되기에 사실상 이 if문은 else가 나올 수 없는 구조였던것이다.

이에 배열에 아이템을 찾을 수 있도록 if문의 컨디션 값을 checkedId.length > 0처럼 확실히 값을 판단 할 수 있도록 하여 해결 하였다.

또, 삭제를 그냥 한번에 querySelectorAll이나 getElementByClassName으로 한꺼번에 잡아 삭제 하는것이 좋다라는 조언을 듣고, delete를 완성하여 문제를 해결 할 수 있었다.

오늘의 교훈

이전부터 true로 취급 되는 값과 false로 취급 되는 값에 대한 정보는 알고 있었지만, 아직 이해가 부족하다는것을 깨달았다.

이번에 확실히 알게 되었으니, 앞으로도 여기저기 응용하고, 사용해보려 한다.

또, 문제의 첫단추가 되는 방법을 MDN에서 실마리를 찾았기에, 앞으로도 공식문서를 자주자주 찾아보려 한다.

물론 배열에 관한 메서드도 공부가 되는 문제였다.

0개의 댓글