HTML, CSS 및 바닐라 JavaScript를 사용하여 프런트 엔드 장바구니 웹 앱 만들기를 막 마쳤습니다. 나는 지역 식료품점에서 야채를 사는 것을 좋아하기 때문에 Finley's Farm Shop이라는 농장 상점의 아이디어를 기반으로 했습니다.
프로젝트를 클릭하려면 라이브 링크를 확인하세요: https://gabrielrowan.github.io/Finleys-Farm-Shop-FE/
이 앱을 사용하면 다음을 수행할 수 있습니다.
? 장바구니에 쇼핑 품목 추가
? 상점 아이템 수량 변경
? 트롤리 모달에서 장바구니에 있는 모든 항목 보기
? 장바구니에 담긴 모든 품목의 총 가격 보기
? 장바구니에 담긴 품목 수 보기
? 페이지를 새로 고치거나 탭을 닫았다가 다시 열어도 장바구니에 모든 항목이 보관됩니다.
저는 지금까지 직장에서 주로 백엔드 애플리케이션 작업을 해왔습니다. 하지만 이번 여름에는 프런트엔드 설계 및 구현을 포함한 풀스택 프로젝트에 참여하게 되었습니다. 정말 즐거웠고 프론트 엔드 기술을 더 발전시키고 싶게 되었습니다.
CSS 라이브러리를 사용하지 않고 이 프로젝트에 도전하고 싶었습니다. CSS 라이브러리를 사용하는 것이 나쁘다고 생각해서가 아니라 프론트엔드에서는 일반적으로 부트스트랩과 같은 것을 사용하기 때문입니다.
저는 이전에 JavaScript와 함께 브라우저 로컬 저장소를 사용한 적이 없었기 때문에 프로젝트를 만드는 것이 실용적인 방법으로 이를 배울 수 있는 가장 좋은 방법이라고 결정했습니다.
처음 이 프로젝트를 시작했을 때 몇 가지 목표를 염두에 두었습니다.
? 반응성 - UI가 모바일, 아이패드, 데스크톱 보기에 적응하기를 원했습니다
? CSS 라이브러리를 사용하지 않고 장바구니 모달을 만들려면
? JavaScript에서 로컬 저장소 사용에 익숙해지려면
프런트 엔드를 만드는 것은 이 프로젝트 계획의 첫 번째 부분입니다. 두 번째 부분은 이것을 Django를 사용하여 풀 스택 앱으로 전환하여 상점 항목이 HTML에 하드코딩되는 대신 데이터베이스에서 나오도록 하는 것입니다.
앱이 다양한 화면 크기에 적응할 수 있도록 하기 위해 Kevin Powell의 이 동영상에 있는 반응형 그리드 버전을 사용했습니다.
.shop-items { display: grid; gap: 0.6rem; grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr)); }
마법은 그리드-템플릿-열 값에 있습니다. 본질적으로 다음을 의미합니다.
최소 크기가 12rem이고 최대 크기가 사용 가능한 공간의 1분할인 이 상위 컨테이너에 가능한 한 많은 열을 맞춥니다.
이 그리드를 사용하면 더 넓은 데스크톱 보기에서 더 좁은 모바일 보기로 이동할 때 추가 미디어 쿼리를 작성할 필요 없이 열의 양(상점 항목 카드의 양으로 표시됨)을 4에서 1로 동적으로 줄일 수 있습니다.
'Finley's Farm Shop'이라는 배너 제목에는 글꼴 크기가 자동으로 조정되도록 클램프()를 사용했습니다. 이렇게 하지 않으면 데스크톱에 잘 어울리는 글꼴 크기가 모바일에는 너무 크다는 것을 알게 되었습니다.
.shop-items { display: grid; gap: 0.6rem; grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr)); }
즉, 글꼴 크기는 5vw(뷰포트 너비 - 전체 표시 화면 너비의 5%라고도 함)를 목표로 합니다.
최소 글꼴 크기는 3.8rem이므로 5vw가 3.8rem보다 작으면 글꼴 크기는 대신 3.8rem이 됩니다.
최대 글꼴 크기는 5.6rem으로 설정되어 있으므로 5vw가 5.6rem보다 크면 글꼴 크기는 5.6rem이 됩니다.
최소 글꼴 크기와 최대 글꼴 크기 사이의 기울기를 정확하게 계산하고 이를 사용하여 원하는 중간 값을 선택하는 방법이 있는데 인스펙터를 사용하여 눈여겨봤습니다 ?
대신 정확한 그라데이션을 계산하는 방법에 대한 CSS Tricks 기사는 다음과 같습니다.
트롤리의 경우 데스크탑 화면 오른쪽에 나타나는 모달을 원했습니다.
모바일 보기에서는 전체 화면 크기를 차지해야 한다고 결정했습니다.
장바구니 항목이 장바구니에 추가되었을 때 장바구니 항목에 대한 CSS에 대부분의 시간을 보냈습니다. 장바구니 항목의 다양한 부분(항목 제목, 'Apple', 가격, 항목 수량 및 이미지)이 내가 계획한 할당 공간을 차지하도록 그리드 템플릿 영역을 사용했습니다.
.banner-title { font-size: clamp(3.8rem, 5vw, 5.6rem); }
모달 JavaScript의 목표는 다음과 같습니다.
이를 달성하기 위해 두 아이콘 모두에ggleModal 함수를 호출하는 이벤트 리스너를 추가했습니다. 모달 요소에 아직 추가되지 않은 경우 .active라는 클래스가 추가되고, 이미 있는 경우 제거됩니다.
CSS에서는 기본적으로 모달이 숨겨지도록 설정하고, .active 클래스는 이를 표시하도록 설정했습니다.
.shop-items { display: grid; gap: 0.6rem; grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr)); }
.banner-title { font-size: clamp(3.8rem, 5vw, 5.6rem); }
이는 닫기 아이콘과 장바구니 아이콘의 이벤트 리스너가 동일한 기능을 재사용할 수 있음을 의미합니다. 모달이 아직 표시되지 않은 경우 표시하고 이미 열려 있는 경우 숨기기 때문입니다.
로컬 저장소의 경우 Web Dev Simplified의 'JavaScript Cookies vs. Local Storage vs. Session Storage' 동영상이 특히 도움이 되었습니다. 데이터를 저장하는 세 가지 방법의 차이점, 개발 도구의 애플리케이션 탭에서 데이터를 보는 방법, 각 데이터 저장 유형에 대한 항목을 추가 및 제거하는 방법에 대해 설명합니다.
장바구니에 항목 2개를 추가한 후 내 프로젝트의 애플리케이션 탭은 다음과 같습니다.
DOM 수정(요소 추가, 요소 제거, 요소 편집)과 관련된 기능과 로컬 저장소와 관련된 기능을 분리하기로 결정했습니다. 예를 들어, 주석에 적힌 대로 수행하며 모달에서 상점 항목 HTML을 제거하는 RemoveCartItemFromModalDOM과는 다른 기능인 RemoveCartItemFromLocalStorage가 있습니다.
.cart-item { display: grid; grid-template-areas: "image description description" "image price quantity"; grid-template-columns: min-content 1fr 1fr; grid-template-rows: 2.5rem 3.5rem; }
이 두 가지 모두 상점 항목이 장바구니에서 제거될 때 호출되어야 하며, 이를 별도의 기능으로 사용하면 프로세스에서 필요한 두 부분을 모두 완료했는지 확인하는 데 도움이 되었습니다. DOM에서 html을 제거하지 않으면 웹 페이지에는 해당 항목이 장바구니에서 삭제되었다는 사실이 시각적으로 반영되지 않습니다. 로컬 저장소에서 항목을 제거하지 않으면 페이지를 새로 고치거나 탭을 닫을 때 변경 사항이 유지될 수 없습니다.
JavaScript에서 로컬 저장 기능을 작업하던 중 정말 당황스러운 문제를 발견했습니다. 지금까지 수행한 단계는 다음과 같습니다.
이리저리 클릭해 보았는데 정말 멋져 보였습니다! ... 페이지를 새로 고칠 때까지. 그런 다음 가격은 이전과 동일한 총계로 설정되었지만 DOM은 초기 페이지 로드 시의 모습으로 완전히 되돌아갔습니다. 시각적으로 장바구니에 항목이 없는 것처럼 보였지만(수량 입력 컨트롤 대신 추가 버튼이 표시됨) 총액이 £0를 넘었습니다.
이 문제는 정말 혼란스러웠고 이해하는 데 시간이 좀 걸렸습니다. 결국 나는 그것을 얻었다. 예, 로컬 저장소에 항목을 추가하고 있었습니다. 그러나 페이지가 다시 로드되고 DOMContentLoaded 이벤트 리스너가 실행되었을 때 로컬 저장소에 있는 내용을 기반으로 DOM을 렌더링하지 않았습니다. 사실 이 단계에서는 로컬 스토리지에 무엇이 있는지 전혀 확인하지 않았습니다.
이 사실을 깨달은 후 로컬 저장소에 있는 제품 배열의 모든 제품을 반복하여 각 제품의 ID를 찾은 다음 관련 제품의 html 요소를 업데이트하여 추가된 제품을 표시하는 DOMContentLoaded라는 함수를 만들었습니다. 카트에.
함수의 단축 버전은 다음과 같습니다.
const loadCartState = () => { const cart = JSON.parse(localStorage.getItem("cart")); 만약 (!카트) { 장바구니 = []; localStorage.setItem("cart", JSON.stringify(cart)); } cart.forEach(제품 => { const shopItem = document.querySelector(`.shop-item[data- > <h2> 전개 </h2> <p>Github Pages를 사용하여 이 앱을 배포했습니다. 이전에는 배포에 사용해 본 적이 없었지만 프로세스가 매우 간단하다는 것을 알았습니다. 내가 만난 유일한 문제는 처음에는 이미지가 전혀 표시되지 않았다는 것입니다. 나는 이것이 대소문자 구분 때문이라는 것을 깨달았습니다. 내 이미지 폴더는 Img라고 불리지만 이미지 경로는 html에서 img/였습니다. 이 문제를 해결하고 캐시를 지운 후 웹사이트가 예상대로 표시되었습니다. </p> <h2> 결론 </h2> <p>저는 이 프로젝트에서 특히 CSS 그리드와 JavaScript로 로컬 저장소를 사용하는 방법에 대해 많은 것을 배웠습니다. 더 많은 페이지를 추가하여 완전한 프런트엔드 전자상거래 앱으로 바꾸고 싶은 유혹이 있었지만, Django 앱으로 만들고 연결하는 다음 단계에 집중할 수 있도록 지금은 MVP를 유지하기로 결정했습니다. 데이터베이스까지 ?</p>
위 내용은 농장 상점을 위한 내 장바구니 프로젝트의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!