쇼핑몰 미니게임 클론 코딩(Dream Coding by 엘리)

25735 단어 JavaScriptCSShtmlCSS

Dream Coding 엘리 선생님의 무료 강의, "쇼핑몰 미니게임 클론 코딩 & 코드 리뷰" 을 들으며 간단한 쇼핑몰 사이트를 따라 만들어보려한다.
아예 강의를 보며 똑같이 입력하면 실력이 절대 늘지 않는다는 선생님의 말씀에 따라, 일단 강의에 올려주신 파일을 사용해서 만들어야겠다는 생각이 들었다. 파일에는 로고와 옷 그림, 그리고 index.html 기본 틀만 있는 정도였다.
body는 일단

  1. 맨 위에 log 박스
  2. 버튼과 옷이 그려져있는 중간부분인 action 박스
  3. 맨 밑에 있는 list
로 나누었다. 사실 맨 밑부분은 선생님이 어떤 기능으로 넣어두신건지 정확히 모르겠어서 수업을 들으면서 따라 해보려한다. 추측컨데 버튼을 눌러서 선택하면 그 데이터가 list에 입력이 되어 출력되는 형식일듯 한데, 아직 JS를 잘 모르니 수업을 듣고 배워야겠다...

얼추 아이템의 배치 정도는 금방 할 수 있게 되었다. 물론 반응형으로 배치가 바뀌고 이런건 지금 안했다. 이제 수업을 들어보고 해봐야지....

수업을 들으면서 따라 만들어보았다.

HTML, CSS에서 기억해야할 내용!

  • alt는 이미지가 보이지 않을때 대신 보이는 글자!
  • 아이템의 class="a b c"이면, a, b, c의 css를 중첩해서 적용!
  • 공통으로 사용되는 색깔, 크기, 애니메이션 등은 css파일의 :root{}에 변수화하고 사용!
  • width와 height를 일정 px로 지정하기 X! %나 vh를 사용하여 비율을 유지!

JavaScript에서 기억해야할 내용!

main.js

//JSON파일에서 아이템 Fetch
function loadItems() {
    return fetch('data/data.json')
    .then(response => response.json())
    .then(json => json.items);
}

//items를 리스트에 업데이트
function displayItems(items) {
    const container = document.querySelector('.items');
    container.innerHTML = items.map(item => creatHTMLString(item)).join('');
}

//data item을 HTML 리스트 아이템으로 만들기
function creatHTMLString(item) {
    return `
    <li class="item">
      <img src="${item.image}" alt="${item.type}" class="item__thumbnail">
      <span class="item__description">${item.gender}, ${item.size}</span>
    </li>
    `;
}

//main
loadItems()
  .then((items) => {
      displayItems(items);
    //   setEventListeners(items);
  })
  .catch(console.log);
  • 어떠한 형태로 동작이 될것인지 골격부터 설계하기!(//main)
    • 아이템 데이터 호출에 성공한다.
      1. 데이터를 출력한다.
      2. 데이터와 관련된 이벤트를 설정한다.
    • 데이터 호출에 실패할 경우, 에러처리를 한다.
  • 함수를 만들면서 계속 결과가 나오는지 확인한다(콘솔을 통해 함수 동작 및 json 출력 확인)
  • json 데이터를 html에 출력할 수 있도록 변환한다.
    1. document.querySelector로 json 데이터 변수 생성(const container)
    2. json을 html형태로 return하는 함수 생성(function createHTMLString(item))
    3. map, join로 container.innerHTML에 하나의 문자열로 담아 업데이트
function onButtonClick(event, items) {
    const dataset = event.target.dataset;
    const key = dataset.key;
    const value = dataset.value;

    if(key == null || value == null) {
        return;
    }

    const filtered = items.filter(item => item[key] === value);
    displayItems(filtered)
}

function setEventListeners(items) {
    const logo = document.querySelector('.logo')
    const buttons = document.querySelector('.buttons')
    logo.addEventListener('click', () => displayItems(items))
    buttons.addEventListener('click', event => onButtonClick(event, items))

}
  • 각 버튼의 이벤트 설정하는 함수 만들기(setEventListeners)
    • logo와 buttons 변수 선언
    • addEventListener를 사용하여 각 변수가 'click'되었을때의 이벤트를 설정
      • logo ==> displayItems(로고를 클릭했을때 모든 아이템 보이기)
      • buttons ==> onButtonClick(클릭한 버튼에 해당하는 아이템만 보이기)
    • 각 버튼의 value에 해당하는 값을 보여주는 onButtonClick 함수 선언
      1. dataset, key, value 변수 선언
      2. key와 value가 null인 경우 함수 종료
      3. filter를 사용하여 클릭한 아이템의 key와 일치하는 value만 걸러내기(filtered 변수)
      4. displayItem함수에 filtered 인자값으로 넣어서 출력


다시보니 분홍색 티셔츠 그림이 있어야할 json 데이터에 분홍색 치마 그림을 넣어버렸다...ㅠㅠ


index.html

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Online Shopping</title>
  <link rel="stylesheet" href="style.css" />
  <script src="src/main.js" defer></script>
</head>

<body>
  <!-- Logo -->
  <img src="img/logo.png" alt="logo" class="logo">

  <!-- Buttons -->
  <section class="buttons">
    <button class="btn"><img src="img/blue_t.png" alt="tshirt" class="imgBtn" data-key="type"
        data-value="tshirt"></button>
    <button class="btn"><img src="img/blue_p.png" alt="pants" class="imgBtn" data-key="type"
        data-value="pants"></button>
    <button class="btn"><img src="img/blue_s.png" alt="skirt" class="imgBtn" data-key="type"
        data-value="skirt"></button>
    <button class="btn colorBtn blue" data-key="color" data-value="blue">Blue</button>
    <button class="btn colorBtn yellow" data-key="color" data-value="yellow">Yellow</button>
    <button class="btn colorBtn pink" data-key="color" data-value="pink">Pink</button>
  </section>

  <!-- Items -->
  <ul class="items">
  </ul>

</body>

</html>

style.css

:root {
  /* color */
  --color-black: #3f454d;
  --color-white: #ffffff;
  --color-blue: #3b88c3;
  --color-yellow: #fbbe28;
  --color-pink: #fd7f84;
  --color-light-grey: #dfdfdf;

  /* size */
  --base-space: 8px;
  --size-button: 60px;
  --size-border: 4px;
  --size-thumbnail: 50px;
  --font-size: 18px;

  /* animation */
  --animation-duration: 300ms;
}

* {
  box-sizing: border-box;
}

body {
  height: 100vh;
  background-color: var(--color-black);
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}

.logo {
  cursor: pointer;
  transition: transform var(--animation-duration) ease;
}

.btn {
  background-color: transparent;
  border: none;
  outline: none;
  cursor: pointer;
  transition: transform var(--animation-duration) ease;
  margin-right: var(--base-space);
}

.logo:hover,
.btn:hover {
  transform: scale(1.1);
}

.buttons {
  display: flex;
  align-items: center;
}

.imgBtn {
  width: var(--size-button);
  height: var(--size-button);
}

.colorBtn {
  font-size: var(--font-size);
  padding: calc(var(--base-space)*2);
  border-radius: var(--size-border);
}

.blue {
  background-color: var(--color-blue);
}

.yellow {
  background-color: var(--color-yellow);
}

.pink {
  background-color: var(--color-pink);
}

.items {
  width: 60%;
  height: 60%;
  list-style: none;
  padding-left: 0;
  overflow-y: scroll;
}

.item {
  background-color: var(--color-white);
  display: flex;
  align-items: center;
  padding: var(--base-space);
  margin-bottom: var(--base-space);
}

.item__thumbnail {
  width: var(--size-thumbnail);
  height: var(--size-thumbnail);
}

.item__description {
  margin-left: var(--base-space);
  font-size: var(--font-size);
}

main.js


//JSON파일에서 아이템 Fetch
function loadItems() {
    return fetch('data/data.json')
    .then(response => response.json())
    .then(json => json.items);
}

//items를 리스트에 업데이트
function displayItems(items) {
    const container = document.querySelector('.items');
    container.innerHTML = items.map(item => creatHTMLString(item)).join('');
}

//data item을 HTML 리스트 아이템으로 만들기
function creatHTMLString(item) {
    return `
    <li class="item">
      <img src="${item.image}" alt="${item.type}" class="item__thumbnail">
      <span class="item__description">${item.gender}, ${item.size}</span>
    </li>
    `;
}

function onButtonClick(event, items) {
    const dataset = event.target.dataset;
    const key = dataset.key;
    const value = dataset.value;

    if(key == null || value == null) {
        return;
    }

    const filtered = items.filter(item => item[key] === value);
    displayItems(filtered)
}

function setEventListeners(items) {
    const logo = document.querySelector('.logo')
    const buttons = document.querySelector('.buttons')
    logo.addEventListener('click', () => displayItems(items))
    buttons.addEventListener('click', event => onButtonClick(event, items))

}

//main
loadItems()
  .then((items) => {
      displayItems(items);
      setEventListeners(items);
  })
  .catch(console.log);

data.json

{
    "items": [
        {
            "type": "tshirt",
            "gender": "female",
            "size": "large",
            "color": "pink",
            "image": "../img/pink_t.png"
        },
        {
            "type": "pants",
            "gender": "male",
            "size": "small",
            "color": "yellow",
            "image": "../img/yellow_p.png"
        },
        {
            "type": "skirt",
            "gender": "male",
            "size": "large",
            "color": "blue",
            "image": "../img/blue_s.png"
        },
        {
            "type": "tshirt",
            "gender": "female",
            "size": "small",
            "color": "yellow",
            "image": "../img/yellow_t.png"
        },
        {
            "type": "skirt",
            "gender": "female",
            "size": "large",
            "color": "pink",
            "image": "../img/pink_s.png"
        },
        {
            "type": "pants",
            "gender": "female",
            "size": "medium",
            "color": "blue",
            "image": "../img/blue_p.png"
        },
        {
            "type": "tshirt",
            "gender": "male",
            "size": "small",
            "color": "pink",
            "image": "../img/pink_s.png"
        }
    ]
}

좋은 웹페이지 즐겨찾기