filter 함수로 minishop 구현하기 (1)

kgorae·2021년 8월 1일
0

스몰 프로젝트

목록 보기
1/8
post-thumbnail

0. 동기

유튜브 드림코딩 by 엘리 채널에 minishop 프로젝트에 PWA 를 사용하는 예시가 올라왔다. minishop 프로젝트는 js 입문용으로 예전부터 소개되고 있었는데, 단순 웹 구현에서 더 나아가 PWA 적용도 배울 수 있는 기회였다. 작은 프로젝트부터 계속 만들어 볼 생각이다.


1. 계획

  1. JSON 으로 items 목록을 받아온다.
  2. 받아온 items 를 화면에 나타낸다.
  3. 버튼에 맞게 필터링하여 보여주도록 한다.
  4. 로고 버튼을 누르면 전체 items 가 나타나게끔 한다.
  5. 리팩토링, PWA

2. 진행

  • js를 활용하는 게 중점이라, mvp.css 를 적용해둔 뒤 js 파일을 먼저 작성하고 css를 작성했다.
  • createElement, appendChild를 먼저 생각했는데, container 의 innerHTML 자체를 변경하면, 필터링 될 때마다 container 를 비워줄 필요가 없어졌다.
  • js 파일 코드 :
'use strict'

//getElementByClassName 과 querySelectorAll 비교 숙지 필요
const container = document.querySelector(".items");
const logo = document.getElementById("logo");
const btn = document.querySelectorAll(".clothes");

// fetch에 적은 url을 통해 json 파일을 받아올 수 있다
// json에서 items 만 받아오기 위해 과정을 한 번 더 거친다.
const loadData = () => fetch("./data.json")
    .then((res)=>res.json())
    .then((json)=>json.items);

const createHTML = (item) => {
    return `<li><img src="${item.img}">
    <span>${item.size}, ${item.gender}</span>
    </li>`
}

const displayItems = (items) => {
    // join("") 이 아니라 join() 하게 되면 중간에 콤마로 구분됨
    container.innerHTML = items.map((item)=>createHTML(item)).join("");
    return items;
}

const setEventListener = (items) => {
    // 로고 누르면 모든 옷 출력
    logo.addEventListener("click", (event) => {displayItems(items)});
    // 버튼에 맞게 필터링 되어 출력
    btn.forEach(button => button.addEventListener("click", (event) => {
        if(event.target.dataset.key === "color"){
            displayItems(items.filter((item) => item.color === event.target.dataset.value));
        } else if(event.target.dataset.key === "type"){
            displayItems(items.filter((item) => item.type === event.target.dataset.value));
        } else {
            displayItems(items);
        }
}))};

loadData()
.then((items) => displayItems(items))
.then((items) => setEventListener(items));

3. 학습 내용

getElementById 와 querySelector 의 결과값은 동일하지만, querySelectorAll 과 비교할 땐 결과가 달라졌다. 구체적으로 학습할 필요가 있었다.

(1) getElementByClassName과 querySelector의 차이

참고) https://guinatal.github.io/queryselector-vs-getelementbyid/

  • getElementsByClassName은 HTMLCollection을 반환하고 querySelectorAll은 NodeList를 반환한다.

(2) HTMLCollection 과 NodeList 의 차이

참고) https://devsoyoung.github.io/posts/js-htmlcollection-nodelist

  • HTMLCollection 과 NodeList 는 제공하는 메서드, 갖고 있는 노드 타입이 각각 다르다.

HTMLCollection

  • HTMLCollection 은 HTML 엘리먼트의 children 프로퍼티에 접근하면 얻을 수 있다.
  • .forEach(), .map() 등의 메서드가 존재하지 않으므로, Array.from() 으로 배열을 만들어서 사용해야 함.

NodeList

  • element.childNodes, querySelectorAll() 로 반환된다.(아래 코드에서 비교)
  • element.childNodes : 라이브 콜렉션 NodeList, DOM 의 변경사항을 실시간으로 반영
  • document.querySelectorAll() : 정적 콜렉션 NodeList, DOM 변경이 콜렉션에 영향 안 줌
const staticNList = document.querySelectorAll('.product');
const dynamicNList = document.body.childNodes;
console.log(staticNList);
console.log(dynamicNList);
// DOM 변경
const input = document.createElement("input");
document.body.appendChild(input);
console.log(staticNList);
console.log(dynamicNList);


(3) dataset

class, id 로 속성값을 생각하기만 했는데 dataset을 이용하면 값 속성을 쉽게 받아올 수 있었다.
https://developer.mozilla.org/ko/docs/Learn/HTML/Howto/Use_data_attributes
https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/dataset


느낀점

  • 함수에서 함수로, 전달하고 전달받는 논리를 구현하는 데 많은 시도가 필요했고, 여전히 고칠 부분이 많아 보인다.
  • 버튼을 누를 때 스크롤 맨 위가 보이게끔 바꾸고, 함수를 더 나은 방법으로 고칠 수 있는지 알아봐야겠다.
  • DOM 에 대해서 더 공부해야겠다.
profile
좋은 개발자, 좋은 사람

0개의 댓글