BOOKREST - HTML DOM Change Animation (6)

한슬희·2021년 8월 4일
2

LIKELION

목록 보기
6/7
post-thumbnail

BOOKREST Notice 페이지 (서비스 소개, 규정, 오시는 길, 문의하기 페이지가 모여있는 곳)을 만들던 도중

"새로고침이 아닌 Animation으로 페이지를 나타내자!!!"

라는 생각이 들었다.

html에서 a링크를 달면 새로고침으로 다른 페이지를 이동하는 것은 매일 하던 거였으니 새로운 걸 해보고 싶었다. 🤔🤔

animation으로 페이지 이동하는 걸 하려면 html에서는 animation을 줄 페이지들을 한 템플릿 안에서 만들어야 한다.

개발

html

  <div class="noticeTool__category">
    <div class="noticeTool__category__title">BOOKREST 이용안내</div>
    <div class="noticeTool__category__link">
      <a class="js-introduceA js-noticeTool__category__link">BOOKREST란</a>
      <a class="js-ruleA js-noticeTool__category__link">규정</a>
      <a class="js-faqA js-noticeTool__category__link">자주 묻는 질문</a>
      <a class="js-bookrestMapA js-noticeTool__category__link">오시는 길</a>
    </div>
  </div>

먼저, a링크를 달아서 내용 폼에 관련한 각각의 제목을 적어준다.
자세한 개발 사항은 a링크 BOOKREST란? , 규정 두 가지로 얘기하도록 하겠다.

class 명은 BEM방식으로 지으려고 노력했다.
👉🏻 CSS BEM 참고

a class="js-introduceA" 를 누르면 나오는 폼

 <div class="noticeTool__summaryTool">
   <!-- js-introduce 여기가 포인트 -->
      <div class="noticeTool__summaryTool__box js-introduce noticeShowing">
        <div class="noticeTool__summaryTool__box__title">
          <h1>BOOKREST란?</h1>
        </div>
        <div class="noticeTool__summaryTool__box__summary">
          BOOKREST는 전공 서적을 대여해주는 서비스입니다. 학기마다 전공 책을
          새로 구매하시나요? 구매하셨다면 가격이 부담스럽지 않으셨나요?
          머라머라머라
        </div>
      </div>
    </div>

a class="js-ruleA" 를 누르면 나오는 폼

    <div class="noticeTool__summaryTool">
      <!-- js-rule 여기가 포인트 -->
      <div class="noticeTool__summaryTool__box js-rule">
        <div class="noticeTool__summaryTool__box__title">
          <h1>Rule</h1>
        </div>
        <div class="noticeTool__summaryTool__box__summary">
          <b>Book</b>
          책의 종류와 재고는 BOOKREST 사이트에서 확인해주시면 됩니다. 직접
          오셔서 대여하려 하시면 이미 예약된 책들도 있어 어려우실 수 있습니다.
          BOOKREST 사이트에서 미리 예약하시면 더 빠르고 쉽게 대여하실 수
          있습니다. 
          머라머라머라
        </div>
      </div>
    </div>

위의 두 폼 모두 한 템플릿에서 쓰인 코드다.
class명, css는 모두 똑같이 먹이고 BEM방식으로 js-introduce, js-rule이라 써주면 모든 준비 완료!


이제 Javascript에서 각각의 a링크를 클릭하면 그에 맞는 폼이 나오도록 만들면 된다.

javascript

// 각각 내용이 있는 폼
const introduce = document.querySelector(".js-introduce");
const rule = document.querySelector(".js-rule");

// a링크
const introduceA = document.querySelector(".js-introduceA"); 
const ruleA = document.querySelector(".js-ruleA");

// css 애니메이션
const NOTICESHOWING_CN = "noticeShowing";

각각의 변수를 선언해준다. noticeShowing에 관한 코드는 아래 있다.

css

.noticeShowing {
  opacity: 1;
  z-index: 10;
  transform: scale(1);
}

noticeShowing은 introduce폼과 rule폼을 보였다 사라졌다 하는 animation을 주는 역할을 한다.

근데 모든 폼이 opacity가 0이면 아무것도 안 보이니 introduce폼이 기본으로 설정해두었다.
따라서 위에 html을 보면 introduce폼 class에 noticeShowing이 적어져 있다.

javascript

const elementList = [introduce, rule];
const elementLinkList = [introduceA, ruleA];
let currentIndex = 0;
let beforeIndex = 0;

elementList 변수는 introduce와 rule 객체(DOM)가 있는 배열이다.
elementLinkList는 각각의 DOM으로 갈 수 있는 링크 태그로 이루어진 배열이다.
currentIndex는 현재 보이는 배열의 인덱스, beforeIndex는 전에 보였던 배열의 인덱스다.

javascript

const noticeInit = () => {
  elementLinkList.map((link, index) => {
    link.addEventListener("click", () => {
      addClassNameToCurrentElement(index);
    });
  });
};

noticeInit();

noticeInit 함수는 제일 먼저 실행되며 elementLinkList 각 요소의 EventListener를 부착한다.
이때 map 메소드의 인덱스 값을 addClassNameToCurrentElement의 인자로 사용한다.

javascript

const addClassNameToCurrentElement = (index) => {
  elementList[beforeIndex].classList.remove(NOTICESHOWING_CN);
  elementList[index].classList.add(NOTICESHOWING_CN);
  beforeIndex = index;
};

link 요소가 click되면 addClassNameToCurrentElement 함수에 index 값을 인자로 실행한다.

elementList 배열의 beforeIndex번째 객체의 classList에 NOTICESHOWING_CN을 지워주고, elementList 배열의 index번째 객체의 classList에 NOTICESHOWING_CN을 더해준다.

beforeIndex = index; beforeIndex에 인덱스 값을 할당해 주었다.
click 되면 beforeIndex번째의 NOTICESHOWING_CN를 지우면 전에 있는 건 안보이고 현재 누른 것만 보이게 되기 때문에 다음에 눌렀을 때를 위해서 beforeIndex 변수에 지금 누른 값인 index를 할당하였다.

결과

url을 보면 같은 한 페이지임을 알 수 있다.
새로고침이 아닌 오른쪽 틀이 animation으로 나오게 된다. 👏🏻👏🏻👏🏻

refactoring 전 ..

const noticeAnimateIntroduce = () => {
  introduce.classList.add(NOTICESHOWING_CN);
  rule.classList.remove(NOTICESHOWING_CN);
  bookrestMap.classList.remove(NOTICESHOWING_CN);
  inquiry.classList.remove(NOTICESHOWING_CN);
};

const noticeAnimateRule = () => {
  rule.classList.add(NOTICESHOWING_CN);
  introduce.classList.remove(NOTICESHOWING_CN);
  bookrestMap.classList.remove(NOTICESHOWING_CN);
  inquiry.classList.remove(NOTICESHOWING_CN);
};

const noticeInit = () => {
  introduceA.addEventListener("click", noticeAnimateIntroduce);
  ruleA.addEventListener("click", noticeAnimateRule);
  bookrestMapA.addEventListener("click", noticeAnimateBookrestMap);
  inquiryA.addEventListener("click", noticeAnimateInquiry);
};

noticeInit();

refactoring 전에는 배열이랑 인덱스를 사용하지 않고 각 요소마다 함수를 만들었다.
하면서도 비효율적이라고 느껴졌다..

만약 더 많은 페이지가 추가된다고 하면 함수를 몇십 개 더 만들어야 하는 거다.
그래서 배열과 인덱스를 활용하였다.

refactoring 후 elementList와 elementLinkList의 배열에 넣어주기만 하면 된다.
const elementList = [introduce, rule];
const elementLinkList = [introduceA, ruleA];

마무리

어떻게 하면 더 효율적인 코드가 될 수 있는지 생각하고 배우며 더 많은 기능의 javascript를 공부해야겠다.

👊🏻👊🏻👊🏻

profile
🧡 Frontend developer / 어제보다 오늘 더 성장한 개발자

2개의 댓글

comment-user-thumbnail
2021년 8월 4일

항상 생각하고 실천하는 자세가 보기좋네요 !!! 많이 배우고 갑니당 🔥🔥🔥🔥

1개의 답글