본문 바로가기

portfolio

AMORE MALL

API Fetch javascript portfolio

#AMOREMALL #모바일 적응형 #데이터비동기처리 #fetch() #json #swiper

📌 PROJECT KEY POINTS

  1. fetch() 함수로 데이터 호출 (feat.JSON)
  2. swiper 사용한 슬라이드

1. fetch() 함수로 데이터 호출 (feat.JSON)

👉🏻 아모레몰의 상품 영역은 거의 비슷한 레이아웃을 가지고 있어 매번 새로운 json 데이터를 만드는 것이 아니라 하나의 prdData.json 파일을 활용. 필요한 부분만 추출해 각 영역의 fetch문에 재사용하여 파일과 코드를 좀 더 간결하게 작성.

  • json
{
  "items":[
    {
      "id":0,
      "thumb": "./assets/img/recom01.png",
      "saleThumb":"./assets/img/sale_first_01.png",
      "brand":"아이오페",
      "name":"슈퍼바이탈 기초 2종 세트 (150ml+150ml)",

      "price":{
        "ori":125000,
        "curr":95000
      },
      "rate": "4.8",
      "review":"(6)",
      "hashtag": "#유수분 밸런스",
      "benefit":[
        "사은품"
      ],
      "cate1":0,
      "cate2":2,
      "cate3":2,
      "sale1":0
    },
    ....
  ]
}
  • js
 fetch("./assets/data/prdData.json")
.then((response) => response.json())
.then((json) => {
  data = json.items;

  let html = '';

  data.forEach(element => {

    benefitHtml = '';
    element.benefit.forEach(benefitEl => {
      benefitHtml += `<span>${benefitEl}</span>`;
    });

    const saleEl = (element.price.ori === element.price.curr) ? 'hide' : '';

    html += `
      <div class="swiper-slide">
        <div class="product-inner">
          <a href="">
            <div class="pro-thumb-area">
              <img src="${element.thumb}" alt="${element.name}" />
            </div>
            <div class="pro-text-area">
              <div class="pro-title">
                <strong class="brand">${element.brand}</strong>
                <span class="name">${element.name}</span>
              </div>
              <div class="pro-price">
                <span class="del-price ${saleEl}">${price(element.price.ori)}</span>
                <em class="discount-rate ${saleEl}">${salepercent(element.price.ori, element.price.curr)}%</em>
                <span class="price"><strong class="size_16">${price(element.price.curr)}</strong>원</span>
              </div>
              <div class="pro-rate">
                <span class="icon-star">
                  <span>${element.rate}</span>
                  <span>${element.review}</span>
                </span>
              </div>
              <div class="pro-gift">${benefitHtml}</div>
            </div>
          </a>
          <button class="pro-like"><span class="blind">좋아요</span></button>
        </div>
      </div>`;
  });

  $('#adviceData').html(html);

🖋 code review

  • fetch("./assets/data/prdData.json") 불러올 json 데이터 파일
  • then((response) => response.json()) 읽어온 데이터를 json으로 변환
  • data = json.items; json에 있는 items만 받아오기
  • data.forEach(element => {})배열의 개수만큼 반복문을 돌리기 위해 사용
  • ${element.name} 형식으로 경로를 작성하여 각 부분에 필요한 데이터를 불러옵니다.
  • saleEl = (element.price.ori === element.price.curr) ? 'hide':''; 할인가가 없어서 판매가만 존재하는 경우를 위한 조건문 -> 'ori'금액과 'curr'의 금액이 같을때'hide'클래스를 추가해 할인가와 할인율을 display:none 시켜주었습니다.
// 천단위 콤마(정규식)
  function price(p) {
    return p.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
  }
  //할인율 함수
  function salepercent(ori, curr) {
    return (ori - curr) / ori * 100;
  }

- 할인율 영역은 데이터 파일에 담겨진 'ori', 'curr'의 값을 이용하여 return 값을 받도록 하였습니다.
- 배열의 요소를 나타내는 문자열을 반환하는 toLocaleString() 메서드를 사용해 가격의 천단위 콤마 정규식 패턴을 사용하였다.


  • js
//첫 페이지에 보여줄 데이터
sortFirst(0, 2);
  
function sortFirst(a, b) {
    sortData(a, b);
    popSkinItems[a].classList.add('active');
    const skinSiblings = Array.from(popSkinItems[a].parentNode.children).filter(el => el !== popSkinItems[a]);
    skinSiblings.forEach(sibling => sibling.classList.remove('active'));
    popTroubleItems[b].classList.add('active');
    const troubleSiblings = Array.from(popTroubleItems[b].parentNode.children).filter(el => el !== popTroubleItems[b]);
    troubleSiblings.forEach(sibling => sibling.classList.remove('active'));
}
  

// 데이터 필터링 해줄 함수
function sortData(cate1, cate2) {
    fetch("./assets/data/prdData.json")
      .then((response) => response.json())
      .then((json) => {
        const data = json.items;

        const result = data.filter((parm) => parm.cate1 == cate1 || parm.cate2 == cate2);

        let html = '';
        result.forEach(element => {
          const saleEl = (element.price.ori === element.price.curr) ? 'hide' : '';

          html += `
		            ... `;//중복으로 생략
        });
        sortDataContainer.innerHTML = html;
      });
}
  • 버튼 클릭시 각 타입에 맞는 상품을 보여주기 위해 fetch문을 함수에 넣어주고 filter() 메서드로 데이터 필터링을 하였습니다.
filter 란❔
자바스크립트에서 filter 는 배열에 사용하며, 주어진 함수를 만족하는 모든 요소를 모아 새 배열로 반환합니다.
  • const result = data.filter(function (parm) {return parm.cate1 == cate1 || parm.cate2 == cate2});
    : cate1, cate2와 맞는 데이터만 나오도록 세팅(두가지 타입 모두 충족하게 하고 싶다면 '&&'사용

💡 ||(or연산자), &&(and연산자)

▪️ json 데이터의 활용

'메인 배너 영역'과 '이벤트 전체보기 팝업 영역'의 데이터가 같아 새로운 파일을 만들지 않고 하나의 JSON 데이터 파일을 활용하여 구현하였습니다.

2. swiper 사용한 슬라이더

  • 페이지 내 대부분에 슬라이더를 사용

-html

<section class="sc-mainbanner swiper" id="banner_swiper">
  <h2 class="blind">메인 배너 영역</h2>
  <div class="swiper-wrapper" id="bannerData1"></div>
  <div class="swiper-page">
    <div class="page-area">
    </div>
    <button class="btn-area" id="allBanner"><span class="blind">전체보기</span></button>
  </div>
</section>

-js

const swiper2 = new Swiper("#banner_swiper", {
    slidesPerView: 'auto',
    spaceBetween: 5,
    loop: true,
    autoplay: {
      delay: 2500,
      disableOnInteraction: false,
    },
    centeredSlides: true,

    // pagination
    pagination: {
      el: ".page-area",
      type: "custom",
      renderCustom: function (swiper, current, total) {

        currentNum = (current < 10) ? '0' + current : current;
        totalNum = (total < 10) ? '0' + total : total;

        return `<span class="page-current">${currentNum}</span> 
          <span class="page-total">${totalNum}</span>`;
      }
    },
  });
🖋 code review
* swiper 사용시 아래 구조와 같은 클래스 명을 지정해줘야 합니다.swiper > swiper-wrapper > swiper-slide
* spaceBetween: 5, css에서 마진값을 주지 않고 swiper의 속성인 spaceBetween은 사용하여 슬라이드의 여백을 설정하였습니다.
* disableOnInteraction: false 마우스 클릭시 슬라이드 멈춤 제어(true: 일시정지, false: 재생)
* pagination을 커스텀하기 위해 type: "custom"으로 바꾸어 주고 renderCustom 속성을 이용해 현재 페이지/전체 페이지수를 표현하였습니다.
* return 값으로 미리 마크업 했던 코드를 사용해 커스텀 하였는데 이때 10 미만의 수에는 앞에 '0'이 붙는 조건문을 사용하여 01/09 형식의 pagination을 구현하였습니다.

💡 Swiper 사용시 주의할 점

  • swiper-wrapper, swiper-slide 클래스 이름 제대로 들어갔는지 확인하기
  • 슬라이더를 여러 개 만들 때 각각의 변수명과 클래스 이름을 다 구분지어주기

 

'portfolio' 카테고리의 다른 글

SEOUL CITY HALL  (0) 2023.07.07
NAVER  (0) 2023.07.07
FLO  (0) 2023.07.07