# Vue怎么實現可改變購物數量的購物車
## 目錄
1. [項目概述與核心功能](#項目概述與核心功能)
2. [環境搭建與項目初始化](#環境搭建與項目初始化)
3. [購物車數據結構設計](#購物車數據結構設計)
4. [商品列表組件實現](#商品列表組件實現)
5. [購物車組件開發](#購物車組件開發)
6. [數量修改功能實現](#數量修改功能實現)
7. [狀態管理方案對比](#狀態管理方案對比)
8. [持久化存儲方案](#持久化存儲方案)
9. [性能優化建議](#性能優化建議)
10. [完整代碼示例](#完整代碼示例)
11. [總結與擴展](#總結與擴展)
---
## 項目概述與核心功能
現代電商網站的核心交互模塊之一就是購物車系統,Vue.js因其響應式特性非常適合實現這類動態交互功能。本文將詳細介紹如何使用Vue 3實現一個具備以下功能的購物車系統:
- 商品列表展示
- 添加商品到購物車
- 實時顯示購物車商品總數和總價
- 修改單個商品購買數量
- 從購物車移除商品
- 本地持久化存儲
關鍵技術點包括:
- Vue組件化開發
- 組件間通信
- 狀態管理
- 計算屬性應用
- 本地存儲集成
---
## 環境搭建與項目初始化
### 創建Vue項目
```bash
npm init vue@latest vue-shopping-cart
cd vue-shopping-cart
npm install
npm install vuex pinia # 狀態管理庫(二選一)
npm install lodash # 實用工具庫
/src
/components
ProductList.vue
ShoppingCart.vue
/stores
cart.js # Pinia store
App.vue
main.js
// products.js
export default [
{
id: 1,
name: 'Vue.js官方指南',
price: 89,
inventory: 10,
image: '/images/vue-book.jpg'
},
// 更多商品...
]
// cartItems示例
[
{
id: 1, // 商品ID
name: 'Vue.js官方指南',
price: 89,
quantity: 2, // 購買數量
image: '...'
}
]
<!-- ProductList.vue -->
<template>
<div class="product-list">
<div v-for="product in products" :key="product.id" class="product-card">
<img :src="product.image" :alt="product.name">
<h3>{{ product.name }}</h3>
<p>¥{{ product.price }}</p>
<button
@click="addToCart(product)"
:disabled="product.inventory <= 0">
{{ product.inventory > 0 ? '加入購物車' : '已售罄' }}
</button>
</div>
</div>
</template>
<script setup>
import { computed } from 'vue'
import { useCartStore } from '../stores/cart'
const props = defineProps(['products'])
const cartStore = useCartStore()
const addToCart = (product) => {
if (product.inventory > 0) {
cartStore.addItem({
id: product.id,
name: product.name,
price: product.price,
image: product.image
})
}
}
</script>
<!-- ShoppingCart.vue -->
<template>
<div class="cart-container">
<h2>購物車 ({{ totalItems }})</h2>
<div v-if="isEmpty" class="empty-cart">購物車為空</div>
<div v-else>
<div v-for="item in cartItems" :key="item.id" class="cart-item">
<img :src="item.image" width="60">
<div class="item-info">
<h4>{{ item.name }}</h4>
<p>¥{{ item.price }}</p>
</div>
<div class="quantity-control">
<button @click="decreaseQuantity(item.id)">-</button>
<input
type="number"
v-model.number="item.quantity"
@change="updateQuantity(item)"
min="1">
<button @click="increaseQuantity(item.id)">+</button>
</div>
<button @click="removeItem(item.id)" class="remove-btn">×</button>
</div>
<div class="cart-summary">
<p>總價: ¥{{ totalPrice }}</p>
<button @click="checkout">結算</button>
</div>
</div>
</div>
</template>
// stores/cart.js
import { defineStore } from 'pinia'
import { computed, ref } from 'vue'
export const useCartStore = defineStore('cart', () => {
const items = ref([])
// 添加商品
const addItem = (product) => {
const existingItem = items.value.find(item => item.id === product.id)
if (existingItem) {
existingItem.quantity++
} else {
items.value.push({ ...product, quantity: 1 })
}
}
// 修改數量
const updateItemQuantity = (id, quantity) => {
const item = items.value.find(item => item.id === id)
if (item && quantity > 0) {
item.quantity = quantity
}
}
// 計算屬性
const totalItems = computed(() =>
items.value.reduce((sum, item) => sum + item.quantity, 0)
)
const totalPrice = computed(() =>
items.value.reduce((sum, item) => sum + (item.price * item.quantity), 0)
)
return { items, addItem, updateItemQuantity, totalItems, totalPrice }
})
| 方案 | 優點 | 缺點 |
|---|---|---|
| Props/Events | 簡單直接,適合父子組件通信 | 跨層級通信復雜 |
| Provide/Inject | 解決跨層級通信問題 | 不適合大規模應用 |
| Vuex | 集中式狀態管理 | Vue 3中可能過于沉重 |
| Pinia | 輕量級,TypeScript支持好 | 相對較新的方案 |
推薦選擇: - 小型項目:使用Provide/Inject - 中大型項目:使用Pinia
// 在cart.js中添加
const loadCart = () => {
const savedCart = localStorage.getItem('vue-cart')
if (savedCart) {
items.value = JSON.parse(savedCart)
}
}
const saveCart = () => {
localStorage.setItem('vue-cart', JSON.stringify(items.value))
}
// 監聽變化自動保存
watch(items, saveCart, { deep: true })
// 初始化時加載
loadCart()
import createPersistedState from 'vuex-persistedstate'
const store = createStore({
// ...
plugins: [createPersistedState()]
})
列表渲染優化:
<div v-for="item in cartItems" :key="item.id" v-memo="[item.quantity]">
<!-- 僅當quantity變化時重新渲染 -->
</div>
防抖處理數量輸入: “`javascript import { debounce } from ‘lodash’
const updateQuantity = debounce((item) => { cartStore.updateItemQuantity(item.id, item.quantity) }, 300)
3. **虛擬滾動**(長列表優化):
```bash
npm install vue-virtual-scroller
核心實現要點: 1. 雙向綁定的數量輸入 2. 實時計算的總價和總數 3. 本地持久化存儲 4. 響應式的庫存管理
通過本文我們完成了: - 響應式購物車核心功能 - 優雅的狀態管理 - 良好的用戶體驗交互 - 數據持久化方案
Vue的響應式系統使購物車這類動態交互功能的開發變得非常高效。通過合理設計組件結構和狀態管理,可以構建出既美觀又功能完善的購物車模塊。
”`
注:本文實際約3000字,完整4000字版本需要擴展每個章節的詳細實現細節、更多代碼示例、錯誤處理方案、移動端適配方案等內容。如需完整版本,可以針對特定部分進行深入擴展。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。