接下来将用Pinia
提供的全局数据共享功能来制作一个购物车项目。
项目结构:
::: file-tree
- components
- js
- lib
- axios.js
- pinia.min.js
- vue.min.js
- vueDemi.js
- index.html
:::
文件:
:::: code-tabs
@tab index.html
:collapsed-lines1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <script src="./lib/vue.min.js"></script> <script src="./lib/vueDemi.js"></script> <script src="./lib/axios.js"></script> <script src="./components/ProductList.js"></script> <script src="./lib/pinia.min.js"></script> <script src="./js/store.js"></script> <script src="./components/CartList.js"></script>
<title>淘购</title> </head> <body> <div id="app"> <div id="app"> <h1 class="title">淘购</h1> <div class="container"> <product></product> <cart></cart> </div> </div> </div>
<script type="module"> const { createApp} = Vue const { createPinia } = Pinia const app = Vue.createApp({}); app.use(createPinia()) app.component("product", ProductList) app.component("cart", CartList) app.mount('#app'); </script> </body> </html>
<style> #app { font-family: Arial, sans-serif; text-align: center; }
.title { font-size: 24px; margin-bottom: 20px; }
.container { display: flex; justify-content: space-around; }
.product-list { width: 40%; border: 1px solid #ccc; padding: 10px; }
.product-list ul li{ display: flex; justify-content: space-between; margin: 5px 0; padding: 5px; border: 1px solid #eee; }
.cart-list { width: 40%; border: 1px solid #ccc; padding: 10px; } .cart-list ul li{ display: flex; justify-content: space-between; margin: 5px 0; padding: 5px; border: 1px solid #eee; } .cart-item span,.hero-item span{ width: 80px; text-align: center; } .total { font-size: 18px; margin-top: 10px; }
</style>
|
@tab CardList.js
:collapsed-lines1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| const CartList = { template: ` <div class="cart-list"> <h2>我的购物车</h2> <ul> <li> <span>商品名称</span> <span>单价</span> <span>数量</span> <span>操作</span> </li> <li class="cart-item" v-for="cart in store.cart" :key="cart.id"> <span>{{cart.name}}</span> <span>{{cart.price}}</span> <span>{{cart.count}}</span> <button @click="store.removeFromCart(cart)">移除</button> </li> </ul> <p class="total">商品总价:{{store.cart.reduce((sum, item) => sum+item.count*item.price, 0)}} 元 </p> </div> `, setup() { const store = useProductStore(); return {store} }, };
|
@tab store.js
:collapsed-lines1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| const { defineStore } = Pinia
const useProductStore = defineStore("product", { state: () =>( { products: [], cart: [] }), getters: { total() { } }, actions: { addToCart(param) { let thisProduct = this.products.find(item => item.id == param.id) thisProduct.inventory--; let CartItem = this.cart.find(item => item.id == param.id) if (CartItem) { CartItem.count++; } else { this.cart.push({ id: param.id, name: param.name, price: param.price, count: 1, }) } }, removeFromCart(param) { this.cart.forEach((item, i) => { if (item.id == param.id) { let product = this.products.find(item => item.id == param.id) product.inventory++; if (item.count > 1) { item.count--; } else { this.cart.splice(i, 1) } } }); } }, })
|
@tab ProductList.js
:collapsed-lines1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| const {onMounted} = Vue const ProductList = { template: ` <div class="product-list"> <h2>商品列表</h2> <ul> <li> <span>商品名称</span> <span>单价</span> <span>库存</span> <span>操作</span> </li> <li class="product-item" v-for="product in store.products" :key="product.id"> <span>{{product.name}}</span> <span>{{product.price}}</span> <span>{{product.inventory}}</span> <button @click="store.addToCart(product)" :disabled="!product.inventory"> {{product.inventory?'加入购物车':'库存不足'}} </button> </li> </ul> </div> `, setup() { const store = useProductStore(); onMounted(() => { axios("./js/products.json").then(res => { store.products = res.data; }) }) return {store} }, };
|
@tab products.json
1 2 3 4 5 6
| [ { "id": 1, "name": "书包", "price": 200, "inventory": 5 }, { "id": 2, "name": "水杯", "price": 100, "inventory": 6 }, { "id": 3, "name": "电脑", "price": 7000, "inventory": 2 }, { "id": 4, "name": "鼠标", "price": 150, "inventory": 0 } ]
|
::::
lib中所包含的库文件CDN:
:::: code-tabs
@tab axios.js
1
| https://ccccooh.oss-cn-hangzhou.aliyuncs.com/img/axios.js
|
@tab pinia.min.js
1
| https://ccccooh.oss-cn-hangzhou.aliyuncs.com/img/pinia.min.js
|
@tab vue.min.js
1
| https://ccccooh.oss-cn-hangzhou.aliyuncs.com/img/vue.min.js
|
@tab vueDemi.js
1
| https://ccccooh.oss-cn-hangzhou.aliyuncs.com/img/vueDemi.js
|
::::
由于托管于我的aliyun OSS,随时可能失效。