Hi,我是布兰妮甜 !在当今数字化时代,电子商务已成为商业领域的重要组成部分。开发一个功能完善、用户友好的在线商店应用对于企业拓展市场至关重要。本文将详细介绍如何使用
Vue2
框架配合ElementUI
组件库开发一个完整的在线商店应用。
文章目录
-
- 一、项目初始化与配置
-
- [1.1 创建Vue2项目](#1.1 创建Vue2项目)
- [1.2 安装ElementUI](#1.2 安装ElementUI)
- [1.3 项目结构规划](#1.3 项目结构规划)
- 二、核心功能模块开发
-
- [2.1 用户认证模块](#2.1 用户认证模块)
- [2.2 商品展示模块](#2.2 商品展示模块)
- [2.3 购物车模块](#2.3 购物车模块)
- 三、状态管理(Vuex)
-
- [3.1 购物车状态管理](#3.1 购物车状态管理)
- 四、路由配置
- 五、API封装与Axios配置
- 六、优化与部署
-
- [6.1 性能优化](#6.1 性能优化)
- [6.2 部署配置](#6.2 部署配置)
- 七、总结
一、项目初始化与配置
1.1 创建Vue2项目
首先,我们需要使用Vue CLI创建一个新的Vue2项目:
bash
vue create online-store
cd online-store
1.2 安装ElementUI
在项目目录中安装ElementUI:
bash
npm install element-ui -S
然后在main.js
中引入ElementUI:
javascript
import Vue from 'vue'
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
Vue.use(ElementUI)
1.3 项目结构规划
text
src/
├── api/ # API请求封装
├── assets/ # 静态资源
├── components/ # 公共组件
├── router/ # 路由配置
├── store/ # Vuex状态管理
├── utils/ # 工具函数
├── views/ # 页面组件
├── App.vue # 根组件
└── main.js # 入口文件
二、核心功能模块开发
2.1 用户认证模块
登录/注册组件
html
<template>
<div class="login-container">
<el-form :model="loginForm" :rules="loginRules" ref="loginForm">
<el-form-item prop="username">
<el-input v-model="loginForm.username" placeholder="用户名"></el-input>
</el-form-item>
<el-form-item prop="password">
<el-input type="password" v-model="loginForm.password" placeholder="密码"></el-input>
</el-form-item>
<el-button type="primary" @click="handleLogin">登录</el-button>
<el-button @click="showRegisterDialog = true">注册</el-button>
</el-form>
<el-dialog title="注册" :visible.sync="showRegisterDialog">
<!-- 注册表单内容 -->
</el-dialog>
</div>
</template>
<script>
export default {
data() {
return {
loginForm: {
username: '',
password: ''
},
loginRules: {
username: [{ required: true, message: '请输入用户名', trigger: 'blur' }],
password: [{ required: true, message: '请输入密码', trigger: 'blur' }]
},
showRegisterDialog: false
}
},
methods: {
handleLogin() {
this.$refs.loginForm.validate(valid => {
if (valid) {
// 调用登录API
this.$store.dispatch('user/login', this.loginForm)
.then(() => {
this.$router.push('/')
this.$message.success('登录成功')
})
}
})
}
}
}
</script>
2.2 商品展示模块
商品列表组件
html
<template>
<div class="product-list">
<el-row :gutter="20">
<el-col :span="6" v-for="product in products" :key="product.id">
<el-card :body-style="{ padding: '0px' }" shadow="hover">
<img :src="product.image" class="product-image">
<div style="padding: 14px;">
<h3>{{ product.name }}</h3>
<div class="price">¥{{ product.price }}</div>
<div class="bottom">
<el-button type="text" @click="showDetail(product)">查看详情</el-button>
<el-button type="primary" size="small" @click="addToCart(product)">加入购物车</el-button>
</div>
</div>
</el-card>
</el-col>
</el-row>
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="pagination.current"
:page-sizes="[12, 24, 36, 48]"
:page-size="pagination.size"
layout="total, sizes, prev, pager, next, jumper"
:total="pagination.total">
</el-pagination>
</div>
</template>
<script>
export default {
data() {
return {
products: [],
pagination: {
current: 1,
size: 12,
total: 0
}
}
},
created() {
this.fetchProducts()
},
methods: {
fetchProducts() {
// 调用API获取商品列表
const { current, size } = this.pagination
getProducts({ page: current, pageSize: size }).then(res => {
this.products = res.data.items
this.pagination.total = res.data.total
})
},
handleSizeChange(val) {
this.pagination.size = val
this.fetchProducts()
},
handleCurrentChange(val) {
this.pagination.current = val
this.fetchProducts()
},
addToCart(product) {
this.$store.dispatch('cart/addToCart', product)
this.$message.success('已加入购物车')
},
showDetail(product) {
this.$router.push(`/product/${product.id}`)
}
}
}
</script>
2.3 购物车模块
购物车组件
html
<template>
<div class="cart-container">
<el-table :data="cartItems" style="width: 100%">
<el-table-column prop="name" label="商品名称"></el-table-column>
<el-table-column prop="price" label="单价" width="120"></el-table-column>
<el-table-column label="数量" width="180">
<template slot-scope="scope">
<el-input-number
v-model="scope.row.quantity"
:min="1"
@change="updateQuantity(scope.row)">
</el-input-number>
</template>
</el-table-column>
<el-table-column label="小计" width="120">
<template slot-scope="scope">
¥{{ (scope.row.price * scope.row.quantity).toFixed(2) }}
</template>
</el-table-column>
<el-table-column label="操作" width="120">
<template slot-scope="scope">
<el-button type="danger" icon="el-icon-delete" circle
@click="removeItem(scope.row.id)">
</el-button>
</template>
</el-table-column>
</el-table>
<div class="total-section">
<span class="total-amount">总计: ¥{{ totalAmount.toFixed(2) }}</span>
<el-button type="primary" @click="checkout">结算</el-button>
</div>
</div>
</template>
<script>
export default {
computed: {
cartItems() {
return this.$store.state.cart.items
},
totalAmount() {
return this.cartItems.reduce((total, item) => {
return total + (item.price * item.quantity)
}, 0)
}
},
methods: {
updateQuantity(item) {
this.$store.dispatch('cart/updateQuantity', {
id: item.id,
quantity: item.quantity
})
},
removeItem(id) {
this.$store.dispatch('cart/removeItem', id)
},
checkout() {
if (this.cartItems.length === 0) {
this.$message.warning('购物车为空')
return
}
this.$router.push('/checkout')
}
}
}
</script>
三、状态管理(Vuex)
3.1 购物车状态管理
javascript
// store/modules/cart.js
const state = {
items: []
}
const mutations = {
ADD_ITEM(state, product) {
const existingItem = state.items.find(item => item.id === product.id)
if (existingItem) {
existingItem.quantity++
} else {
state.items.push({
...product,
quantity: 1
})
}
},
UPDATE_QUANTITY(state, { id, quantity }) {
const item = state.items.find(item => item.id === id)
if (item) {
item.quantity = quantity
}
},
REMOVE_ITEM(state, id) {
state.items = state.items.filter(item => item.id !== id)
},
CLEAR_CART(state) {
state.items = []
}
}
const actions = {
addToCart({ commit }, product) {
commit('ADD_ITEM', product)
},
updateQuantity({ commit }, payload) {
commit('UPDATE_QUANTITY', payload)
},
removeItem({ commit }, id) {
commit('REMOVE_ITEM', id)
},
clearCart({ commit }) {
commit('CLEAR_CART')
}
}
export default {
namespaced: true,
state,
mutations,
actions
}
四、路由配置
javascript
// router/index.js
import Vue from 'vue'
import Router from 'vue-router'
import Home from '../views/Home.vue'
import ProductList from '../views/ProductList.vue'
import ProductDetail from '../views/ProductDetail.vue'
import Cart from '../views/Cart.vue'
import Checkout from '../views/Checkout.vue'
import Login from '../views/Login.vue'
Vue.use(Router)
const router = new Router({
mode: 'history',
routes: [
{
path: '/',
name: 'home',
component: Home
},
{
path: '/products',
name: 'products',
component: ProductList
},
{
path: '/product/:id',
name: 'product-detail',
component: ProductDetail,
props: true
},
{
path: '/cart',
name: 'cart',
component: Cart,
meta: { requiresAuth: true }
},
{
path: '/checkout',
name: 'checkout',
component: Checkout,
meta: { requiresAuth: true }
},
{
path: '/login',
name: 'login',
component: Login
}
]
})
// 路由守卫
router.beforeEach((to, from, next) => {
const isAuthenticated = store.getters['user/isAuthenticated']
if (to.matched.some(record => record.meta.requiresAuth) {
if (!isAuthenticated) {
next({ name: 'login', query: { redirect: to.fullPath } })
} else {
next()
}
} else {
next()
}
})
export default router
五、API封装与Axios配置
javascript
// utils/request.js
import axios from 'axios'
import { Message } from 'element-ui'
const service = axios.create({
baseURL: process.env.VUE_APP_BASE_API,
timeout: 5000
})
// 请求拦截器
service.interceptors.request.use(
config => {
const token = localStorage.getItem('token')
if (token) {
config.headers['Authorization'] = `Bearer ${token}`
}
return config
},
error => {
return Promise.reject(error)
}
)
// 响应拦截器
service.interceptors.response.use(
response => {
const res = response.data
if (res.code !== 200) {
Message({
message: res.message || 'Error',
type: 'error',
duration: 5 * 1000
})
return Promise.reject(new Error(res.message || 'Error'))
} else {
return res
}
},
error => {
Message({
message: error.message,
type: 'error',
duration: 5 * 1000
})
return Promise.reject(error)
}
)
export default service
六、优化与部署
6.1 性能优化
-
组件懒加载 :
javascriptconst ProductList = () => import('../views/ProductList.vue')
-
路由懒加载 :
javascript{ path: '/products', component: () => import('../views/ProductList.vue') }
-
CDN引入 :
javascript// vue.config.js module.exports = { configureWebpack: { externals: { 'vue': 'Vue', 'element-ui': 'ELEMENT' } } }
6.2 部署配置
javascript
// vue.config.js
module.exports = {
publicPath: process.env.NODE_ENV === 'production' ? '/online-store/' : '/',
outputDir: 'dist',
assetsDir: 'static',
productionSourceMap: false,
devServer: {
proxy: {
'/api': {
target: 'http://your-api-server.com',
changeOrigin: true,
pathRewrite: {
'^/api': ''
}
}
}
}
}
七、总结
本文详细介绍了如何使用Vue2和ElementUI开发一个功能完整的在线商店应用。我们从项目初始化开始,逐步实现了用户认证、商品展示、购物车管理等核心功能模块,并介绍了状态管理、路由配置、API封装等关键技术点。
通过ElementUI丰富的组件库,我们能够快速构建出美观、响应式的用户界面,而Vue2的响应式特性和组件化开发模式则大大提高了开发效率和代码可维护性。
希望本文能为开发者提供一个全面的参考,帮助您快速构建自己的在线商店应用。