์ฐธ๊ณ ํ ๊ฒ์๋ฌผ >
https://xn--xy1bk56a.run/vuex/3-cart/#%EC%95%A1%EC%85%98-%EC%B6%94%EA%B0%80
1. ์ฅ๋ฐ๊ตฌ๋ ๊ธฐ๋ฅ ๊ตฌํ
** ์ปดํฌ๋ํธ ํด๋ ๊ตฌ์กฐ **
Vuex (store/index.js) |
|
์ฅ๋ฐ๊ตฌ๋ ๋ด๊ธฐ ๋ฒํผ๊ณผ ๋ฉ์๋ (ProductPage.vue) |
์ฅ๋ฐ๊ตฌ๋ ๋ทฐ (AddedProductList.vue) |
** ์ฅ๋ฐ๊ตฌ๋ ๊ด๋ จ ๋ฒํผ ๊ธฐ๋ฅ **
'+ ๋ฒํผ' ํด๋ฆญ์ | '- ๋ฒํผ' ํด๋ฆญ์ |
product์ inventory -1 cartItem์ quantity +1 cartItem์ itemtotalprice + ์ํ๊ฐ๊ฒฉ |
product์ inventory +1 cartItem์ quantity -1 cartItem์ itemtotalprice - ์ํ๊ฐ๊ฒฉ |
์ดํฉ๊ณ = ์นดํธ์ ๋ด๊ธด ์ํ์ ์ด ๊ฐ๊ฒฉ |
1) ์คํ ์ด์ state, actions, mutations, getters ์ถ๊ฐ(store/index.js)
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export const store = new Vuex.Store({
// ์คํ ์ด ๊ฐ์ฒด ์ต์
์ค์
state: {
products: [
{
id: 0,
title: "๊ฐ์์ง ์ฌ๋ฃ",
description: "์์ ๊ฐ์์ง ์ฌ๋ฃ์
๋๋ค.",
price: 15000,
img: "../assets/images/dogfood.jpg",
inventory: 10,
},
{
id: 1,
title: "๊ณ ์์ด ์ฌ๋ฃ",
description: "์์ ๊ณ ์์ด ์ฌ๋ฃ์
๋๋ค.",
price: 20000,
img: "../assets/images/dogfood.jpg",
inventory: 10,
},
{
id: 2,
title: "์ ์ฌ๋ฃ",
description: "์์ ์ ์ฌ๋ฃ์
๋๋ค.",
price: 5000,
img: "../assets/images/dogfood.jpg",
inventory: 1,
},
{
id: 3,
title: "๋ฏธ์ด์บฃ ์ฌ๋ฃ",
description: "์์ ๋ฏธ์ด์บฃ ์ฌ๋ฃ์
๋๋ค.",
price: 25000,
img: "../assets/images/dogfood.jpg",
inventory: 2,
},
{
id: 4,
title: "ํ์คํฐ ์ฌ๋ฃ",
description: "์์ ํ์คํฐ ์ฌ๋ฃ์
๋๋ค.",
price: 10000,
img: "../assets/images/dogfood.jpg",
inventory: 30,
},
{
id: 5,
title: "๊ฑฐ๋ถ์ด ์ฌ๋ฃ",
description: "์์ ๊ฑฐ๋ถ์ด ์ฌ๋ฃ์
๋๋ค.",
price: 2000,
img: "../assets/images/dogfood.jpg",
inventory: 0,
},
],
cart: [],
},
actions: {
//'+'๋ฒํผ ํด๋ฆญ ์
addOrder({state, commit}, product) {
//์ ํ์ ๋จ์ ์๋์ด ์์ ๊ฒฝ์ฐ
if ( product.inventory > 0 ) {
const productItem = state.products.find(item => item.id === product.id);
const cartItem = state.cart.find(item => item.productId === product.id);
if (!cartItem) {
commit('pushProductToCart', productItem); //์ถ๊ฐํ ์ ํ์ด ์ฅ๋ฐ๊ตฌ๋์ ์ ํ๊ณผ ์ผ์นํ์ง ์์ ๊ฒฝ์ฐ, ์ฅ๋ฐ๊ตฌ๋์ ์๋ก ์ถ๊ฐ
} else {
if( product.inventory > 0 ) {
commit('incrementItemQuantity', cartItem); //์ผ์นํ ๊ฒฝ์ฐ, ์ฅ๋ฐ๊ตฌ๋์ ์ ํ ์๋์ ์ฆ๊ฐ}
}
}
commit('decrementProductInventory', productItem); //๋จ์ ์๋ -1
commit('incrementItemTotalPrice', cartItem); //๊ฐ๊ฒฉ๋ณ๊ฒฝ
}
//์ ํ์ ๋จ์ ์๋์ด ์๋ ๊ฒฝ์ฐ
else {
alert("๋จ์์๋ ์์");
}
},
//'-'๋ฒํผ ํด๋ฆญ ์
subOrder({state, commit}, product) {
//์ฅ๋ฐ๊ตฌ๋์ ๋ด๊ธด ์์ดํ
์ด ์์ ๊ฒฝ์ฐ
const cartItem = state.cart.find(item => item.productId === product.id);
if (cartItem.quantity > 0) {
commit('decrementItemQuantity', cartItem); //์ฅ๋ฐ๊ตฌ๋์ ์ ํ ์๋ -1
commit('incrementProductInventory', product); //๋จ์ ์๋ +1
commit('decrementItemTotalPrice', cartItem); //๊ฐ๊ฒฉ๋ณ๊ฒฝ
}
//์ฅ๋ฐ๊ตฌ๋์ ๋ด๊ธด ์์ดํ
์ด ์์ ๊ฒฝ์ฐ
else {
alert("์ฅ๋ฐ๊ตฌ๋์ ๋ด์ ์๋ ์์");
}
}
},
mutations: {
//์ฅ๋ฐ๊ตฌ๋์ ์ ํ์ ์ถ๊ฐ
pushProductToCart(state, product) {
state.cart.push({
productId: product.id,
title: product.title,
price: product.price,
quantity: 1,
inventory: product.inventory,
itemtotalprice: product.price,
});
},
//์ผํ ์นดํธ์ ์์ดํ
์๋ ์ฆ๊ฐ
incrementItemQuantity(state, cartItem) {
cartItem.quantity++;
},
//์ผํ ์นดํธ์ ์์ดํ
์๋ ๊ฐ์
decrementItemQuantity(state, cartItem) {
cartItem.quantity--;
},
// ์์ดํ
์ ๋จ์ ์๋ ์ฆ๊ฐ
incrementProductInventory(state, product) {
product.inventory++;
},
// ์์ดํ
์ ๋จ์ ์๋ ๊ฐ์
decrementProductInventory(state, product) {
product.inventory--;
},
//๊ฐ๊ฒฉ๋ณ๊ฒฝ
incrementItemTotalPrice(state, cartItem) {
cartItem.itemtotalprice += cartItem.price;
},
//๊ฐ๊ฒฉ๋ณ๊ฒฝ
decrementItemTotalPrice(state, cartItem) {
cartItem.itemtotalprice -= cartItem.price;
},
},
getters: {
getcartProducts(state) {
return state.cart.map(cartItem => {
const product = state.products.find(product => product.id === cartItem.productId);
if(product === undefined) {
return {
quantity: 0,
itemtotalprice: 0,
}
} else return {
id: product.id,
title: product.title,
price: product.price,
inventory: product.inventory,
quantity: cartItem.quantity,
itemtotalprice: cartItem.itemtotalprice,
};
});
},
getcartProductsthis:(state) => (productItem) => {
const cartItem = state.cart.find(item => item.productId === productItem.id);
const product = state.products.find(product => product.id === productItem.id);
if(cartItem === undefined) {
return {
quantity: 0,
itemtotalprice: 0,
}
}
return {
product : product.title,
quantity: cartItem.quantity,
itemtotalprice: cartItem.itemtotalprice,
};
},
cartTotal(state) {
let total = 0;
state.cart.forEach(cartItem => {
total += cartItem.itemtotalprice;
});
return total;
},
},
})
2) ์ฅ๋ฐ๊ตฌ๋ ๋ด๊ธฐ ๋ฒํผ๊ณผ ๋ฉ์๋(ProductPage.vue)
<template>
<div id="productpage">
<div id="productsimple">
<div class="product-img">
<img src="../assets/images/dogfood.jpg" alt />
</div>
<div class="product-simpleinfo">
<ul>
<li class="title" v-text="product.title"></li>
<li class="des" v-text="product.description"></li>
<li class="price">{{ product.price }}์</li>
</ul>
<div>๋จ์ ์๋ : {{ product.inventory }}๊ฐ</div>
<div id="editquantity">
<button @click="subOrder(product)">-</button>
<div>
{{ $store.getters.getcartProductsthis(product).quantity }}
</div>
<button @click="addOrder(product)">+</button>
</div>
<div class="total">
์ดํฉ๊ณ : {{ $store.getters.getcartProductsthis(product).itemtotalprice }}์
</div>
</div>
</div>
<div id="productdetail"></div>
</div>
</template>
<script>
export default {
name: "ProductPage",
data() {
const index = this.$route.params.contentId;
return {
product: this.$store.state.products[index]
};
},
methods: {
addOrder(product) {
this.$store.dispatch("addOrder", product);
},
subOrder(product) {
this.$store.dispatch("subOrder", product);
},
},
};
</script>
3) ์ฅ๋ฐ๊ตฌ๋ ๋ทฐ(AddedProductList.vue)
<template>
<div id="addedproductlist">
<div>
<div>
<div
v-if="$store.getters.getcartProducts.length === 0"
class="shopped-item"
>
์ฅ๋ฐ๊ตฌ๋์ ๋ด์ ์ํ์ด ์์ต๋๋ค.
</div>
<div
v-else
class="shopped-item"
:key="index"
v-for="(cartproduct, index) in $store.getters.getcartProducts"
>
<div class="shopped-imgtitle">
<img src="../assets/images/dogfood.jpg" />
<div class="shopped-title">{{ cartproduct.title }}</div>
</div>
<div id="editquantity">
<button @click="subOrder(cartproduct)">-</button>
<div>
{{ cartproduct.quantity }}
</div>
<button @click="addOrder(cartproduct)">+</button>
</div>
<div class="shopped-price">
{{ cartproduct.itemtotalprice }}์
</div>
</div>
<div class="shopped-total">
์ด ๊ฐ๊ฒฉ : {{ $store.getters.cartTotal }}์
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: "AddedProductList",
methods: {
addOrder(cartproduct) {
this.$store.dispatch("addOrder", cartproduct);
},
subOrder(cartproduct) {
this.$store.dispatch("subOrder", cartproduct);
}
},
};
</script>
2. ์ฅ๋ฐ๊ตฌ๋ ๊ธฐ๋ฅ ํ ์คํธ
1) ProductPage.vue
- +-๋ฒํผ ํด๋ฆญ ์
- +-๋ฒํผ ํด๋ฆญํ ํ
2) AddedProductList.vue
์ฅ๋ฐ๊ตฌ๋์ ์๋ ์นดํธ๋ชฉ๋ก์ ๋ณด๋ฉด ๋ด๊ธด ์ํ๋ค์ ํ์ธํ๊ฑฐ๋ ์ํ ๊ฐ์๋ฅผ ์กฐ์ ํ ์ ์๋ค!
'๐ก์น ํ๋ก์ ํธ > (ํ๋ก ํธ์๋) ๋ง์ผ์ปฌ๋ฆฌ - ํด๋ก ์ฝ๋ฉ' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
์ฃผ์ ์ ๋ ฅ ๊ตฌํ(daum ์ฃผ์ api) (0) | 2021.08.04 |
---|---|
vuex ์ํ๋ณ ๋ฆฌ๋ทฐ ๋ทฐ์ด (0) | 2021.07.20 |
vuex ๋ฐ์ดํฐ ์ ๋ฌ(์์->ํ์) (0) | 2021.07.17 |
vue์ ๋ถํธ์คํธ๋ฉ ์ ์ฉ (0) | 2021.07.16 |
vue ํ๋ก์ ํธ ์์ฑ (0) | 2021.07.16 |