쇼핑 카트 뷰
쇼핑 카트의 기능은 구현되었지만, 사용자에게 쇼핑 카트 뷰(View)를 제공해야 합니다. 쇼핑 카트 컴포넌트를 만들어 UI를 구현해봅니다.
ShoppingCart 컴포넌트
ShoppingCart
컴포넌트 파일을 만든 후 템플릿 코드를 작성합니다.
<!-- components/ShoppingCart.vue -->
<div class="shopping-cart">
<h1>장바구니</h1>
<table>
<caption>장바구니에 담긴 도서</caption>
<tr>
<th>제목</th>
<th>가격</th>
<th>수량</th>
</tr>
<tr v-for="book in books" :key="book.id">
<td>{{ book.name }}</td>
<td>{{ book.price }}</td>
<td>{{ book.quantity }}</td>
</tr>
<tr>
<th>총계</th>
<td colspan="2">{{ total }}</td>
</tr>
</table>
</div>
NOTE
사용자가 쇼핑 카트에 추가한 도서 book
데이터의 모형은 다음과 같습니다.
book = { name, price, quantity }
컴포넌트 계산된 속성 books
, total
을 추가한 후 스토어의 게터로부터 계산된 값을 가져오는 코드를 작성합니다.
// components/ShoppingCart.vue
export default {
name: 'ShoppingCart',
computend: {
books() {
return this.$store.getters.cartBooks;
},
total() {
return this.$store.getters.cartTotal;
}
}
}
App.vue
에서 ShoppingCart.vue
를 불러와
쇼핑 카트를 화면에 렌더링 하는 코드를 작성합니다.
// App.vue
<template>
<div id="app">
<BookList/>
<hr>
<ShoppingCart/>
</div>
</template>
<script>
import BookList from "./components/BookList.vue";
import ShoppingCart from "./components/ShoppingCart.vue";
export default {
name: "app",
components: {
BookList,
ShoppingCart
}
};
</script>
cartBooks, cartTotal 게터
컴포넌트가 요구하는 계산된 값을 제공하기 위해 스토어에 cartBooks
, cartTotal
게터를 추가합니다.
// store/index.js
getters: {
cartBooks(state) {
return state.cart.map(cartItem => {
const book = state.books.find(book => book.id === cartItem.id);
return {
id: book.id,
price: book.price,
quantity: cartItem.quantity
};
});
},
cartTotal(state, getters) {
let total = 0;
getters.cartBoooks.forEach(cartItem => {
total += cartItem.price * cartItem.quantity;
});
return total;
}
}
NOTE
배열 객체의 reduce 메서드를 사용해 cartTotal
게터를 작성할 수도 있습니다.
cartTotal(state, getters) {
return getters.cartBoooks.reduce((total,cartItem) => total + cartItem.price * cartItem.quantity, 0);
}
원화 필터
도서의 가격(숫자)을 원화로 필터링 하는 필터를 정의합니다.
// filters/won.js
export default function won(value) {
return
`${String(value)
.split('')
.reverse()
.map((c,i) => ((i > 0 && i % 3 === 0) ? c + ',' : c))
.reverse()
.join('')} 원`;
}
모든 컴포넌트에서 원화 필터를 사용할 수 있도록 글로벌 필터로 등록합니다.
// main.js
import won from './filters/won';
Vue.filter('won', won);
BookList
, ShoppingCart
컴포넌트에 원화 필터를 사용합니다.
<!-- components/BookList.vue -->
<div class="book-list">
<h1>도서 목록</h1>
<img v-if="loading" src="https://i.imgur.com/JfPpwOA.gif" alt="로딩 중...">
<ul v-else>
<li v-for="(book,i) in books" :key="i">
{{ book.name }} / {{ book.price | won }}
<button
type="button"
@click="addBookToCart(book)"
>카트에 추가</button>
</li>
</ul>
</div>
<!-- components/ShoppingCart.vue -->
<template>
<div class="shopping-cart">
<h1>장바구니</h1>
<table border="1" v-if="books.length">
<caption>장바구니에 담긴 도서</caption>
<tr>
<th>제목</th>
<th>가격</th>
<th>수량</th>
</tr>
<tr v-for="book in books" :key="book.id">
<td>{{ book.name }}</td>
<td>{{ book.price | won }}</td>
<td>{{ book.quantity }}</td>
</tr>
<tr>
<th>총계</th>
<td colspan="2">{{total | won}}</td>
</tr>
</table>
</div>
</template>