강의를 보고 JSON을 활용한 간단한 쇼핑몰을 만들어 보며 정리한 것들이다.
✍️ 작성메모
1) CSS 파일에서 공통적으로 사용되는 속성값들은 변수로 정의하기
:root {
/* color */
--color-black: #3f454d;
--color-white: #ffffff;
--color-blue: #3b88c3;
--color-yellow: #fbbe28;
--color-pink: #fd7f84;
--color-light-grey: #dfdfdf;
/* size */
--size-space: 8px;
--size-button: 60px;
--size-font: 18px;
--size-border: 4px;
--size-thumbnail: 50px;
/* annimation */
--animation-duration: 300ms;
}
2) HTML 파일에서 퍼스널 프로퍼티 적용시키기
{
"items": [
{
"type": "tshirt", // 여기서 key는 type, value는 tshirt이다.
"gender": "female",
"size": "large",
"color": "pink",
"image": "../img/pink_t.png"
},
{
"type": "pants",
"gender": "male",
"size": "large",
"color": "blue",
"image": "../img/blue_p.png"
},
{...} // 모든 아이템 항목들을 작성
]
}
1) Data 보관하기
(1) HTML에 데이터를 넣기
: 동적 처리를 할 때, UI적 요소인 HTML안에 데이터와 HTML요소가 함께 섞인 것은 좋지 않다. 그러므로 목록의 아이템을 따로 추출해서 보관하자.
(2) JavaScript에 데이터를 넣기
: js는 어플리케이션의 비즈니스 로직(코드)을 담당하는 곳이므로, 코드와 데이터가 함께 보관되는 것은 피하는 것이 좋다.
▶ 데이터는 데이터를 보관할 수 있는 특별한 장소에 보관하는 것이 좋다.(ex. file, database, back-end서비스 등) 여기서는 data라는 폴더안에 json파일을 이용해서 보관했다.
2) JSON 파일에 데이터 정의하기
"items"는 배열이고, 배열 안에는 item들이 들어있다. item은 다시 오브젝트이기 때문에 key와 value로 구성된다.
오브젝트 안에는 해당하는 모든 관련 자료를 묶어서 담아야 한다. 즉, 아이템에 관련된 이미지(경로지정)까지도 포함해서 넣는다.
개발툴-네트워크를 통해서 페이지로딩시 어떤 것들이 다운받아지는지 알 수 있다. data폴더-json파일에 데이터를 정의 하였으므로 다운로드가 되어있지 않은 상태이다.
1. main호출 작성하기 (구현하기 전에 큰 틀 짜기)
loadItems()
.then(items => {
displayItems(items);
setEventListeners(items);
})
.catch(console.log)
loadItems()
: data.json의 아이템을 읽어와서 아이템을 전달해주는 함수, 프로미스를 리턴한다.
.then(items => {})
: 프로미스가 잘 되면 아이템을 받아온다.
displayItems(items);
: 받아온 아이템을 html에 보여주는 함수이다.
setEventListeners(items);
: 받아온 아이템과 이벤트리스너를 통해서 버튼 클릭 시 필터링을 해주는 함수이다.
.catch(console.log)
: 프로미스가 잘 안되면 콘솔 출력을 하기로 한다.
2. JSON 파일로부터 아이템을 동적으로 받아오기
function loadItems(){
return fetch('data/data.json')
.then(response => response.json())
.then(json => json.items);
}
fetch
를 이용해서 데이터를 받아온 다음, 받은 데이터가 성공적이면 JSON으로 변환하고, JSON안에있는 items
를 리턴하는 함수이다.
브라우저 API 중 하나인 fetch
fecth
는 데이터를 성공적으로 받아오면 response라는 오브젝트를 전달해준다.개발툴-네트워크를 통해서 JSON이 다운된 것을 확인할 수 있게 되었다.
response.json()
: response 오브젝트가 가지고 있는 json()이라는 API를 이용한다.
response body를 오브젝트로 변환 → 콘솔로 출력하면 data.json에 정의한 아이템들이 출력된다.
3. 받아온 아이템으로 목록 업데이트하기
function displayItems(items){
const container = document.querySelector('.items');
container.innerHTML = items.map(item => createHTMLString(item)).join('');
}
// 주어진 아이템에서 HTML 목록 만들기
function createHTMLString(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>
`;
}
items
인자를 받아오고 이 데이터를 HTML요소로 변환해서 페이지에 표기되도록 하는 함수이다.
document.querySelector
를 이용, 컨테이너 요소.items
를 정의한다. (여기에서는 부모컨테이너안에 추가해야 하므로)
element.innerHTML
: element 안의 HTML이나 XML을 가져온다.
map() & join()
▶ 배열메소드(2)
: 받아온 items
에 map()
을 사용해서 li
그룹으로 만들어서 컨테이너에 추가하고, 문자열의 배열을 join()
을 이용해서 한 가지의 문자열로 병합한다.
createHTMLString
: 각각 아이템을 받아와서 함수를 이용, 아이템을li
태그(요소 문자열)로 만들어 주도록 한다.
template string
: 문자열, 변수, 코드, 등을 중간중간 넣어 쓸 수 있는 문자열 템플릿의 장점을 활용하자.
4. 받아온 아이템과 이벤트리스너를 통해서 버튼 클릭 시 아이템 필터링하기
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));
}
// 버튼이 클릭 되었을 때 처리되는 함수
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);
}
items
를 전달받아서 버튼클릭동작을 정의하는 함수이다.
document.querySelector
를 통해서 로고와 버튼을 정의한다.
버튼이 들어있는 컨테이너 자체에 이벤트 리스너를 등록 => 이벤트 위임 이라고 한다. (각각에 이벤트 리스너를 등록하는 것보다 컨테이너 하나에 등록함으로써 한곳에서 핸들링 할 수 있도록 만들 수 있다.)
logo
가 선택되면 모든 아이템들이 보여지도록 설정한다.
buttons
가 클릭되면 이벤트가 발생할 수 있도록 해주고, 아이템도 전달한다.
이벤트 처리 함수는 on~~ 식으로 명명하면 구분하고 알아보기 좋다.
items
에 있는 배열에 filter()
를 이용 → item
이라는 오브젝트 안에 [key]
에 해당하는 값이 value
와 같은 것들만 필터링 해서 displayItems
로 전달한다.
✍️ 자세히 이해하기
1) JSON 파일로부터 아이템을 동적으로 받아오기 파트
function loadItems(){
return fetch('/data/myData.json')
// .then(a => console.log(a)) fetch를 통해 받아온 데이터 확인
.then(a => a.json())
// .then(b => console.log(b)) .json()을 통해 받아온 데이터 확인
.then(b => b.Jitems)
// .then(c => console.log(c)) Jitems의 전체 배열 확인
}
.then(a => console.log(a))
: fetch 를 통해 받아온 데이터 확인 ▼
-> body와 headers, http의코드 (status)가 성공했는지 실패했는지, fecth가 이용한 url등을 볼 수 있다. 여기서 우리가 원하는 데이터는 body 안에 있다.
.then(b => console.log(b))
: .json()을 통해 받아온 JSON파일 내부의 배열 확인 ▼
.then(c => console.log(c))
: JSON파일 내부의 .Jitems 배열 확인 ▼
2) 받아온 아이템으로 목록 업데이트하기 파트
function displayItems(i1){
const container = document.querySelector('.myItems')
container.innerHTML = i1.map(i2 => createHTMLString(i2)).join('');
}
function createHTMLString(i3){ // li문자열 배열로 변환하기
return`
<li class="item">
<img src="${i3.image}" alt="${i3.type}" class="item__thumbnail">
<span class="item__description">${i3.gender}, ${i3.size}</span>
</li>
`
}
container.innerHTML = i1; console.log(container.innerHTML);
container.innerHTML = i1.map(i2 => createHTMLString(i2)); console.log(container.innerHTML);
: map() 메소드를 적용할 경우 ▼
container.innerHTML = i1.map(i2 => createHTMLString(i2)).join(''); console.log(container.innerHTML);
: 구분자를 넣은 join('') 메소드를 적용할 경우 ▼ (만약 구분자에 아무것도 넣지 않으면 ,
로 구분되어 이전 단계와 똑같이 출력되는 것을 알 수 있었다.)
3) 버튼 클릭 시 아이템 필터링하기 파트
function setEventListeners(i1){
const logo = document.querySelector('.logo');
const Btn = document.querySelector('.buttons');
logo.addEventListener('click', () => displayItems(i1));
Btn.addEventListener('click', e => onButtonClick(e, i1));
}
function onButtonClick(e1, i2){
const data = e1.target.dataset;
const key = data.key;
const value = data.value;
if(key == null || value == null){
return;
}
const filtered = i2.filter(i3 => i3[key] === value);
displayItems(filtered);
}
function onButtonClick(e1, i2){
const data = e1;
console.log(data);
};
function onButtonClick(e1, i2){
const data = e1.target;
console.log(data);
};
function onButtonClick(e1, i2){
const data = e1.target.dataset;
console.log(data);
};
function onButtonClick(e1, i2){
const data = e1.target.dataset;
const key = data.key;
const value = data.value;
console.log(key, value);
};
const filtered = i2.filter(i3 => i3[key] === value);
displayItems(filtered);
4) 선택한 버튼과 각각의 배열이 서로 매칭될 수 있도록 작동되는 부분(아이템 필터링)
// HTML 커스텀 프로퍼티
data-key="type" data-value="pants"
data-key="type" data-value="skirt"
data-key="type" data-value="tshirt"
data-key="color" data-value="blue"
data-key="color" data-value="yellow"
data-key="color" data-value="pink"
// js
function onButtonClick(e1, i2){
const data = e1.target.dataset;
const key = data.key // type과 color 두가지
const value = data.value; // skirt, pants, tshirt & pink, blue, yellow
const filtered = i2.filter(i3 => i3[key] === value);
displayItems(filtered); // 화면에 전달
data-
HTML문법event.target.dataset.key
와 event.target.dataset.value
를 이용한다.reference)
dream_coding