정보교육/프런트엔드
코딩 자율학습단(Vue.js 프런트엔드 개발 입문) 15일차
@thiskorea
2024. 7. 4. 20:11
9장 Pinia로 상태 관리하기
9.4 실습: Pinia를 사용해 장바구니 앱 만들기
1. 뷰 애플리케이션 초기화
//vue.js.frontend/ch09_cart/src/router/index.js
import { createRouter, createWebHistory } from 'vue-router'
import HomeView from '../views/HomeView.vue'
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: [
{
path: '/',
name: 'home',
component: HomeView
},
{
path: '/cart',
name: 'cart',
// route level code-splitting
// this generates a separate chunk (About.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import('../views/CartView.vue')
}
]
})
export default router
// vue.js.frontend/ch09_cart/src/stores/cart.js
import { reactive } from 'vue'
import { defineStore } from 'pinia'
export const useCartStore = defineStore('cart', () => {
const item = reactive([
{
id: 1,
name: 'banana',
price: 1000,
},
{
id: 2,
name: 'orange',
price: 3000,
},
{
id: 3,
name: 'mango',
price: 5000,
},
{
id: 4,
name: 'apple',
price: 4000,
},
]);
const cartItem = reactive([]); // 장바구니 아이템
return { item, cartItem }
})
// vue.js.frontend/ch09_cart/src/views/CartView.vue
<script setup>
</script>>
<template>
<h1>장바구니 목록</h1>
</template>
// vue.js.frontend/ch09_cart/src/views/HomeView.vue
<script setup>
</script>>
<template>
<h1>상품 목록</h1>
</template>
// vue.js.frontend/ch09_cart/src/App.vue
<script setup>
import { RouterLink, RouterView } from 'vue-router'
</script>
<template>
<RouterView />
</template>
// vue.js.frontend/ch09_cart/src/main.js
// import './assets/main.css'
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'
import router from './router'
const app = createApp(App)
app.use(createPinia())
app.use(router)
app.mount('#app')
2. 상품 목록 구현하기
// vue.js.frontend/ch09_cart/src/views/HomeView.vue
<script setup>
import { useCartStore } from '@/stores/cart';
import { storeToRefs } from 'pinia';
const cartStore = useCartStore();
// item 비구조화 할당
const { item } = storeToRefs(cartStore);
// 장바구니에 상품 추가 기능, cartItem에 id 추가
const inCart = (id) => {
cartStore.cartItem.push(id);
};
// 장바구니에 상품 삭제 기능, cartItem에 id 삭제
const outCart = (id) => {
cartStore.cartItem = cartStore.cartItem.filter((v) => v !== id);
};
</script>>
<template>
<h1>상품 목록</h1>
<RouterLink to="/cart">장바구니</RouterLink>
<ul>
<li
v-for="it in item"
:key="it.id"
:class="{ in: cartStore.cartItem.includes(it.id)}">
<span>{{ it.name }}</span>
<span>{{ it.price }}</span>
<button
v-if="!cartStore.cartItem.includes(it.id)"
@click="inCart(it.id)">담기</button>
<button v-else @click="outCart(it.id)">삭제</button>
</li>
</ul>
</template>
<style scoped>
.in {
text-decoration: line-through;
}
</style>
3. 장바구니 구현하기
// vue.js.frontend/ch09_cart/src/views/CartView.vue
<script setup>
import { useCartStore } from '@/stores/cart';
import { computed } from 'vue';
const cartStore = useCartStore();
// cartItem에 포함되어 있지 않은 item 값만 필터링
const cartItem = computed(() => {
return cartStore.item.filter((v) => cartStore.cartItem.includes(v.id));
});
// cartItem 스테이트 값 비우기
const allClear = () => {
cartStore.cartItem = [];
};
// 장바구니에 담긴 전체 금액을 합산해 alert()으로 보여주기
const payCart = () => {
const price = cartItem.value.reduce((prev, cur) => {
return prev + cur.price;
}, 0);
alert('총 ${price.toLocaleString()}원을 결제하시겟습니까?');
};
// 장바구니에서 상품 삭제 기능
const outCart = (id) => {
// cartStore.cartItem = cartStore.cartItem.filter((v) => v !== id); 이 코드는 HomeView와 중복되어 스토어에 보냄.
cartStore.outCart(id);
};
</script>
<template>
<h1>장바구니 목록</h1>
<RouterLink to="/">Home</RouterLink>
<ul v-if="cartItem.length > 0">
<li v-for="item in cartItem">
<span>{{ item.name }}</span>
<span>{{ item.price }}</span>
<button @click="outCart(item.id)">삭제</button>
</li>
</ul>
<p v-else>장바구니가 비어 있습니다</p>
<button @click="payCart">결제</button>
<button @click="allClear">전체 비우기</button>
</template>