基于Vue.js开发的购物车应用,利用其响应式数据特性实现商品管理核心功能,通过data选项存储商品列表(含id、名称、价格、数量等属性),methods定义添加商品、增减数量、删除商品等操作方法,computed计算属性实时动态统计商品总数量及总金额,采用组件化拆分,将商品项封装为独立子组件,提升代码复用性,结合v-for指令渲染商品列表,v-model绑定数量输入,事件处理实现交互逻辑,同时可集成localStorage实现购物车数据持久化,刷新页面后数据不丢失,整体实现简洁高效,依赖Vue的响应式机制,确保数据变化时视图自动更新,提升用户体验。
Vue.js实战:构建一个功能完整的购物车应用
在电商和各类在线服务中,购物车作为用户与商品交互的核心模块,其功能完整性、交互流畅性直接影响用户体验,Vue.js凭借其响应式数据绑定、组件化开发和简洁的API,成为构建动态购物车应用的理想选择,本文将以Vue 3为基础,结合组合式API,一步步实现一个包含商品展示、添加/删除商品、数量调整、价格计算等核心功能的购物车应用,并探讨状态管理和功能扩展的思路。
项目准备
技术栈
- 前端框架:Vue 3(组合式API)
- 构建工具:Vite(快速初始化项目)
- 状态管理:Pinia(Vue 3官方推荐,替代Vuex)
- 样式处理:CSS(或预处理器如SCSS,本文以原生CSS为例)
- 开发工具:VS Code(推荐安装Volar和ESLint插件)
初始化项目
使用Vite创建Vue 3项目:
npm create vite@latest vue-shopping-cart -- --template vue cd vue-shopping-cart npm install
安装Pinia:
npm install pinia
在main.js中初始化Pinia:
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'
import './assets/main.css' // 导入全局样式
const app = createApp(App)
app.use(createPinia())
app.mount('#app')
核心功能实现
商品列表展示
我们需要模拟商品数据并展示在页面上。
商品数据定义
在src/data/products.js中模拟商品列表:
export const products = [
{
id: 1,
name: 'Vue.js实战书籍',
price: 89,
image: 'https://via.placeholder.com/150',
description: '深入浅出Vue.js开发技巧与实践'
},
{
id: 2,
name: 'Node.js权威指南',
price: 129,
image: 'https://via.placeholder.com/150',
description: 'Node.js全栈开发权威指南'
},
{
id: 3,
name: 'JavaScript高级程序设计',
price: 99,
image: 'https://via.placeholder.com/150',
description: '前端开发必读经典'
},
{
id: 4,
name: 'CSS权威指南',
price: 79,
image: 'https://via.placeholder.com/150',
description: 'CSS布局与设计技巧大全'
},
]
商品列表组件
创建src/components/ProductList.vue,展示商品并支持"加入购物车":
<template>
<div class="product-list">
<h2>商品列表</h2>
<div class="products">
<div v-for="product in products" :key="product.id" class="product-card">
<img :src="product.image" :alt="product.name" class="product-image" />
<h3>{{ product.name }}</h3>
<p class="description">{{ product.description }}</p>
<p class="price">¥{{ product.price }}</p>
<button @click="addToCart(product)">加入购物车</button>
</div>
</div>
</div>
</template>
<script setup>
import { products } from '../data/products'
import { useCartStore } from '../stores/cart'
import { toast } from 'vue3-toastify'
import 'vue3-toastify/dist/index.css'
const cartStore = useCartStore()
const addToCart = (product) => {
cartStore.addItem(product)
toast.success(`${product.name} 已加入购物车`, {
autoClose: 2000,
position: 'top-right'
})
}
</script>
<style scoped>
.product-list {
padding: 20px;
max-width: 1200px;
margin: 0 auto;
}
.products {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
gap: 25px;
}
.product-card {
border: 1px solid #e0e0e0;
border-radius: 12px;
padding: 20px;
text-align: center;
background: white;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
transition: transform 0.3s, box-shadow 0.3s;
}
.product-card:hover {
transform: translateY(-5px);
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.15);
}
.product-image {
width: 100%;
height: 180px;
object-fit: cover;
border-radius: 8px;
margin-bottom: 15px;
}
h3 {
font-size: 1.2rem;
margin: 10px 0;
color: #333;
}
.description {
color: #666;
font-size: 0.9rem;
margin: 8px 0;
height: 40px;
overflow: hidden;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
.price {
color: #e74c3c;
font-weight: bold;
font-size: 1.1rem;
margin: 12px 0;
}
button {
background: #3498db;
color: white;
border: none;
padding: 10px 20px;
border-radius: 6px;
cursor: pointer;
transition: background 0.3s, transform 0.2s;
font-weight: 500;
}
button:hover {
background: #2980b9;
transform: scale(1.05);
}
button:active {
transform: scale(0.98);
}
</style>
购物车状态管理(Pinia)
购物车的数据(如商品列表、总价)需要跨组件共享,使用Pinia可以集中管理状态。
创建Pinia Store
在src/stores/cart.js中定义购物车状态:
import { defineStore } from 'pinia'
export const useCartStore = defineStore('cart', {
state: () => ({
items: [], // 购物车商品:{ id, name, price, quantity, image }
}),
getters: {
// 计算购物车总商品数量
totalItems: (state) => state.items.reduce((sum, item) => sum + item.quantity, 0),
// 计算购物车总价
totalPrice: (state) => state.items.reduce((sum, item) => sum + item.price * item.quantity, 0),
// 检查商品是否已在购物车中
isInCart: (state) => (productId) => {
return state.items.some(item => item.id === productId)
},
// 获取购物车中特定商品的数量
getItemQuantity: (state) => (productId) => {
const item = state.items.find(item => item.id === productId)
return item ? item.quantity : 0
}
},
actions: {
// 添加商品到购物车
addItem(product) {
const existingItem = this.items.find(item => item.id === product.id)
if (existingItem) {
// 如果商品已存在,增加数量
existingItem.quantity++
} else {
// 如果商品不存在,添加新项
this.items.push({
...product,
quantity: 1
})
}
},
// 从购物车移除商品
removeItem(productId) {
const