[WEB] ~6/6 공부.log

이찬형·2020년 6월 6일
2
post-thumbnail

지금까지..

과제 + 수업에 프로젝트까지.. 생각보다 많이 바쁘네요ㅠㅠ
그 동안 공부하면서 실수했던 것, 구현한 것을 살짝 정리하겠습니다.

resize 시 fixed된 엘리먼트 배치

동아리에서 인스타그램 클론코딩 과제가 나왔는데, 추천 창을 어떻게 배치해야할지 모르겠어서 고민했습니다.

이 영역은 resize 되어도 항상 게시글 옆에 붙어있어야 해요.
물론 스크롤을 내려도 저 위치에 고정되어야 합니다.

단순히 생각하면 position: fixed로 고정해놓으면 되지만 브라우저의 크기가 달라지면 두 레이아웃 사이의 간격이 이상해질 수도 있겠죠??

방법은 굉장히 여러 가지가 있을 거예요. 게시글 영역과 추천 영역을 고정 사이즈로 묶어놓고 처리를 하던가.. 근데 이렇게 하면 flex 속성들이 뭉게질 수도 있어서 JS를 사용하기로 했습니다.

function handleResize() {
  let offset = container.offsetLeft + 610 + 20;
  recommend.style.left = `${offset}px`;
  header.style.padding = `0 ${container.offsetLeft}px`;
}

function init() {
  let offset = container.offsetLeft + 610 + 20;
  recommend.style.left = `${offset}px`;
  header.style.padding = `0 ${container.offsetLeft}px`;
}

게시글의 크기를 610px로 고정해놓았다고 할게요.
스크립트가 로딩되면 컨테이너(=게시글 블록)가 브라우저의 왼쪽에서 얼마나 떨어져 있는지 알려주는 값인 offsetLeft에 게시글의 크기인 610px을 더해서 추천 창의 left 값으로 주면 게시글 블록 옆에 딱 붙게 돼요.

자연스럽게 해주기 위해 저는 20px를 추가로 더해주었습니다.

이 함수를 이벤트 리스너로 resize될 때 걸어주면 됩니다.

추가적으로 헤더의 패딩을 스크립트로 설정을 해줬는데, 이렇게 할 필요 없이 css의 max-width 속성을 쓰면 해당 크기 이상으로 커지지 않더라구요.. 알아두면 좋을 것 같습니다.

모달 창

특정 버튼을 눌렀을 때 팝업과 같이 뜨는 창을 모달이라고 해요.
얘도 css 클래스를 이용해서 display 속성만 바꿔주면 됩니다.

포인트는 모달이 아닌 다른 곳을 클릭했을 때에도 모달이 닫히도록 만들어주는 것인데요!!

우선 widthheight 속성이 브라우저의 크기만큼 꽉 찬 div를 하나 만들고, z-index를 10정도 준 후 숨깁니다.

모달을 여는 버튼을 클릭했을 때, 숨겨저 있던 div를 보여주고 그 위에 모달 창을 띄워요.

이 때 window 객체에 click 이벤트 리스너를 열어서 모달이 아닌, 뒷 배경이 클릭됐을 경우 모달을 닫는 로직을 만들어주면 됩니다.

코드는 다음과 같아요.

function handleClick() {
  bg.style.height = `${document.body.scrollHeight}px`;
  modal.classList.remove("hide");
  bg.classList.remove("hide");
  body.style.overflow = "hidden";
}

function handleOutsideClick(event) {
  if (event.target === bg) {
    modal.classList.add("hide");
    bg.classList.add("hide");
    body.style.overflow = "scroll";
  }
}

아코디언 레이아웃

FAQ 페이지를 아코디언 레이아웃을 이용해 만들었어요.
라이브러리를 사용하려고 했지만 디자인을 수정하기 힘들어서 바닐라로 구현했습니다.

원리는 굉장히 간단해요.
아코디언 제목을 눌렀을 때 숨겨놨던 아코디언 내용을 보이게 해주면 됩니다. 모달 만들 때처럼 클래스를 add / remove 하는거예요.

<div className="accordian-wrapper">
    <a href="#content-2" className="accordian-toggle">
     질문 2
    </a>
    <div className="accordian-content" id="content-2">
     답변 2
    </div>
</div>

타이틀에 답변 div의 id값을 링크를 걸어두었습니다.
이벤트 리스너로 해당 타이틀을 클릭 시 답변 div를 다루기 위해서예요.

let content = document.querySelector(event.target.hash);

이제 이 친구에게 active 클래스를 넣었다 뺐다 하면 끝이겠네요.
css는 아래와 같이 작성했어요.

.accordian-content {
  display: flex;
  align-items: center;
  z-index: -10;
  transition: all 0.2s ease-in-out;
  width: 100%;
  padding-left: 15px;
  border-radius: 10px;
  background-color: #ffeaa7;
  max-height: 0;
  overflow: hidden;
  padding: 0 20px;
  line-height: 30px;
}

.accordian-content.active {
  max-height: 500px;
  padding: 20px;
}

display 속성을 none 에서 block 으로 바꿔도 상관이 없지만, 이는 transition 속성이 작동을 하지 않아요.

따라서 자연스럽게 열리는 애니메이션을 주기 위해 max-height를 주었습니다.

아코디언 - 이벤트 리스너, useEffect

리액트에서도 위 코드를 그대로 썼어요.
컴포넌트가 마운트 됐을 때 useEffect로 이벤트 리스너 열고, handleClick 함수를 적용했습니다.

그런데 다른 페이지로 갔다가 돌아오니 아코디언이 작동하지 않았습니다...

어떨 땐 되고, 어떨 땐 안되고.. 콘솔에 찍어보니 한 번 클릭했는데 굉장히 많은 이벤트가 실행이 되더라구요.

원인은 컴포넌트가 unmount 될 때 removeEventListener를 안 해주었던 것 때문이었습니다ㅠㅠ

useEffect(() => {
  document.addEventListener("click", handleClick);
  return () => document.removeEventListener("click", handleClick);
}, []);

스크롤 애니메이션

항상 애플 사이트 보면서 이런건 어떻게 만드는건지 궁금했어요.
마침 인프런에 애플 사이트 클론코딩 강의가 보여서!! 바로 사버렸습니다.

진짜 지금까지 들었던 강의 중 손에 꼽을만큼 재밌는 강의였어요. 50%정도 들었는데 시간가는 줄 모르고 들었습니다.

지금까지 들으면서 느낀 점은, 비율 계산만 잘 해주면 어떤 애니메이션이던 구현이 가능하겠구나..!! 입니다. 이게 제일 어렵더라구요.

내용이 어려워서 수학 공식 쓰듯이 적어가며 들었습니다ㅠㅠ
대신 결과물이 진짜 말이 안나와요.. 특히 뒷 배경으로 동영상 돌아갈 때 기절할 뻔 했습니다.

앞으로..

6월까지 프론트엔드 끝장을 보겠다란 마인드로 시작했는데, 아직 한참 부족한 것 같아요 ㅋㅋㅋ

그래도 JS와 그 어떤 언어보다 친해졌고, getElementById도 모르던 제가 디버깅을 해가며 웹페이지를 만들고 있네요.

몇 번을 봐도 이해가 안 가던 콜백함수와 여러 동작방식들이 이젠 당연한 듯이 여겨집니다. 힘들게 배운 만큼 뿌듯하네요 ㅎㅎ..

슬슬 Node.js를 건드릴 때가 온 것 같아요. 서버리스 개발만 하다보니 로그인같은 기본적인 기능도 구현을 못 하는 경우가 많아서..

잘 마무리 하고 서버사이드도 공부를 시작하겠습니다.

파이팅!!

profile
WEB / Security

0개의 댓글