今天一樣是實作簡單 Shopping cart 主要練習,數據驅動 UI
我們是一間高級餐廳,每日會提供限量餐點,因為預訂的客戶太多希望可以開發一套餐點預訂系統。
使用 <router-link :to="{name: 'shop'}"
router-link 可以直接套用 class 所以看起來像 button
因為 vuex 流程關係,改變 state 才需要重新計算一次,
這段計算可以輕鬆的在 getter 做,
因為要先撈出庫存單點,(總不能推薦的餐點已經沒有庫存囉)。
然後隨機取一個餐點出來 show 在購物車結帳頁面上面推薦。
如果使用者 加購
或 取消
餐點,會因為 state 改變,而取得新的推薦餐點 (如果沒改只是剛好隨機數一樣)
getRecommendedProducts: state => {
// 先取得庫存餐點表
const inventoryList = state.products.filter(p => p.inventory > 0);
// 取隨機數
const random = Math.round(Math.random() * (inventoryList.length - 1));
// 回傳隨機數的餐點
return inventoryList[ random ];
}
取消預訂單純操縱產品與購物車陣列,從購物車移除物件,產品庫存加一。
[types.CANCEL_CART] (state, title) {
// 從購物車移除
// ES6 array findIndex 找到條件成立的物件,所在陣列中的位子。
const cartIndex = state.shoppingCart.findIndex(item => item.title === title);
state.shoppingCart.splice(cartIndex, 1);
// 餐點庫存 +1
const product = state.products.find(item => item.title === title);
product.inventory += 1;
},
<template>
<div class="container">
<nav class="navbar navbar-default">
<div class="container-fluid">
<div class="navbar-header">
<button type="button" class="collapsed navbar-toggle" data-toggle="collapse" data-target="#bs-example-navbar-collapse-5" aria-expanded="false">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a href="#" class="navbar-brand">Shopping Cart</a>
</div>
<div class="collapse navbar-collapse navbar-right">
<router-link :to="{name: 'cart'}" class="btn navbar-btn">
<span class="glyphicon glyphicon-shopping-cart" aria-hidden="true"></span>
<span class="badge">{{ cartTotal }}</span>
</router-link>
</div>
</div>
</nav>
<!-- Recommended Products -->
<div class="recommend">
<div class="row">
<div class="col-md-3">
<img :src="recommend.image" style="width: 100%;">
</div>
<div class="col-md-9">
<div class="recommend-info">
<h2>{{ recommend.title }}</h2>
<hr>
<h3>Just some random text, lorem ipsum text praesent tincidunt ipsum lipsum. Just some random text, Once again, some random text to lorem lorem lorem lorem ipsum text praesent tincidunt ipsum lipsum.
</h3>
<h2>${{ recommend.price }}</h2>
<button
class="btn btn-danger"
@click="addCart( recommend.title )">
<span class="glyphicon glyphicon-shopping-cart" aria-hidden="true"></span>
加購
</button>
</div>
</div>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading panel-price">總計: <span>${{ total }}</span> 元</div>
<table class="table">
<thead>
<tr>
<th>項目</th>
<th>價錢</th>
<th>餐點</th>
<th>取消預訂</th>
</tr>
</thead>
<tbody>
<tr v-for="(cart, index) in cartList">
<td>{{ index + 1 }}</td>
<td>{{ cart.price }}</td>
<td>{{ cart.title }}</td>
<td>
<button
class="btn btn-default btn-xs glyphicon glyphicon-remove"
@click="cancelCart(cart.title)">
</button>
</td>
</tr>
</tbody>
</table>
</div>
<div class="row">
<div class="col-md-6 center-block">
<router-link :to="{name: 'shop'}" class="btn btn-warning btn-lg btn-block">
<span class="glyphicon glyphicon-arrow-left" aria-hidden="true"></span>
back to Shop
</router-link>
</div>
<div class="col-md-6 center-block">
<button class="btn btn-success btn-lg btn-block center-block">
<span class="glyphicon glyphicon-usd" aria-hidden="true"></span>
buy now
</button>
</div>
</div>
</div>
</template>
<script>
import { mapGetters, mapActions } from 'vuex'
export default {
computed: mapGetters({
cartTotal: 'getShoppingCartTotal',
cartList: 'getShoppingCart',
total: 'getCartPriceTotal',
recommend: 'getRecommendedProducts'
}),
methods: mapActions([
'cancelCart',
'addCart'
]),
}
</script>
實作小範例入門 Vue & Vuex 2.0 - github 完整範例
使用 git checkout 切換每天範例。