在当今数字化购物的浪潮中,购物车功能已成为电商平台不可或缺的一部分。它不仅承担着记录用户所选商品的重任,还需提供流畅的交互体验和精准的计算逻辑。本文将深入探讨如何利用 Vue.js 这一强大的 JavaScript 框架,逐步搭建一个基础但功能完备的购物车系统。
一、项目初始化与 HTML 结构搭建
我们从一个标准的 HTML5 文档开始,在<head>
标签中设置好字符编码为 UTF - 8,以确保支持各种语言字符的正确显示。同时,通过<meta name="viewport" content="width=device-width, initial-scale=1.0">
这一设置,让页面能够自适应不同设备的屏幕尺寸,无论是在电脑、平板还是手机上,用户都能获得一致的浏览体验。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>基础购物车</title>
</head>
接着构建购物车的主体结构,所有内容都包裹在一个具有id="app"
的<div>
元素内,这是 Vue.js 实例挂载的目标容器。购物车主要由一个表格<table>
来展示商品信息,表格的<thead>
部分定义了表头,清晰地标注出 “商品名称”“商品价格”“商品数量” 和 “操作” 这几个关键信息栏。
<div id="app">
<table cellspacing="0">
<thead>
<tr>
<td>商品名称</td>
<td>商品价格</td>
<td>商品数量</td>
<td>操作</td>
</tr>
</thead>
在<tbody>
部分,我们使用 Vue.js 的v - for
指令来循环渲染商品列表。v - for
指令遍历goodsList
数组,为每个商品项生成对应的表格行。同时,通过:key
绑定唯一的键值,帮助 Vue.js 高效地更新和管理 DOM 元素。
<tbody>
<template v - for="(item, index) in goodsList" :key="index">
<tr :class="item.num > 0? 'active' : ''">
<td>{{item.name}}</td>
<td>¥{{item.price.toFixed(2)}}</td>
<td>
<button @click="reduce_num(index)" v - if="item.num > 0? true : false">-</button>
{{item.num}}
<button @click="add_num(index)">+</button>
</td>
<td>
<button @click="editGoods(index)">编辑</button>
<button @click="removeGoods(index)">删除</button>
</td>
</tr>
</template>
</tbody>
表格下方,有一个<div class="summary">
用于显示购物车的总价和总数量,方便用户随时了解购物车的整体情况。再往下,是添加商品的按钮和用于添加或编辑商品信息的输入框区域,该区域通过v - show
指令根据showEdit
变量的值来控制显示与隐藏。
<div class="summary">
总价:¥{{totalPrice.toFixed(2)}} 总数量:{{total}}
</div>
<div>
<button @click="addGoods()">添加</button>
<div class="edit_content" v - show="showEdit">
<input v - model="newGoods.name" placeholder="商品名称" class="input">
<input v - model="newGoods.price" @input="NumberInput($event)" type="text" placeholder="商品价格" class="input">
<input v - model="newGoods.num" @input="NumberInput($event)" type="text" placeholder="商品数量" class="input">
<div>
<button @click="sure_edit()">确定</button>
<button @click="close_edit()">取消</button>
</div>
</div>
</div>
二、CSS 样式美化
为了让购物车页面看起来更美观、易读,我们使用了一些基本的 CSS 样式。首先,通过* { margin: 0; padding: 0; }
来重置浏览器的默认内外边距,确保所有元素的布局起点一致。
* {
margin: 0;
padding: 0;
}
对于表格,设置了border: 1px black solid;
,为表格添加黑色的 1 像素边框,使其结构更加清晰。表格的行<tr>
和单元格<td>
都设置了固定宽度width: 100px;
,并通过text - align: center;
使内容居中显示,同时也添加了边框,让表格的每一个部分都一目了然。
table {
border: 1px black solid;
}
tr,
td {
width: 100px;
text - align: center;
border: 1px black solid;
}
为了突出显示有库存(商品数量大于 0)的商品行,定义了.active
类。当商品数量满足条件时,通过:class
指令动态应用该类,改变行的背景颜色为红色,文字颜色为白色,增强视觉上的区分度,方便用户快速识别可购买的商品。
.active {
background - color: red;
color: white;
}
对于输入框,设置outline: none; border: 1px solid #ccc;
样式。outline: none;
去除输入框获得焦点时默认的外边框效果,使其看起来更加简洁;border: 1px solid #ccc;
则为输入框添加了浅灰色的 1 像素边框,与整体页面风格保持协调。
.input {
outline: none;
border: 1px solid #ccc;
}
三、Vue.js 核心逻辑实现
(一)响应式数据定义
在 Vue 3 的setup()
函数中,我们定义了两个关键的响应式数据。newGoods
是一个响应式对象,用于收集用户输入的新商品信息,包括商品名称name
、价格price
和初始数量num
。Vue.js 的响应式系统会自动追踪对这个对象属性的任何修改,并实时更新到页面上。
// 响应式对象用于新商品输入
const newGoods = reactive({
name: '',
price: 0,
num: 1
});
goodsList
是一个响应式数组,存储了购物车中的所有商品项。初始时,数组中包含一个示例商品,方便我们在开发和测试过程中查看购物车的基本展示效果。随着用户添加、编辑或删除商品,这个数组会动态变化,页面也会相应地更新显示。
// 响应式数组用于商品列表
const goodsList = reactive([{
name: '商品1',
price: 10,
num: 1
}]);
(二)商品操作功能实现
- 删除商品:
removeGoods(index)
函数负责从goodsList
数组中删除指定下标的商品项。它使用 JavaScript 数组的splice()
方法,该方法会改变原数组。当用户点击商品操作栏中的 “删除” 按钮时,对应的商品下标会作为参数传递给这个函数,从而实现商品的删除操作,并且页面会自动刷新以反映这一变化。
// 删除商品
function removeGoods(index) {
goodsList.splice(index, 1);
}
- 增加和减少商品数量:
add_num(index)
函数用于将指定商品的数量num
加 1。当用户点击商品数量旁边的 “+” 按钮时,该函数被触发,商品数量增加,同时总价和总数量也会根据新的数量自动重新计算并更新显示。
// 增加数量
function add_num(index) {
goodsList[index].num++;
}
reduce_num(index)
函数则在商品数量大于 0 的前提下将其减 1。当商品数量大于 0 时,用户点击 “-” 按钮,该函数执行,商品数量减少。通过这种方式,用户可以方便地调整购物车中商品的数量。
// 减少数量
function reduce_num(index) {
if (goodsList[index].num > 0) {
goodsList[index].num--;
}
}
(三)计算属性:总价与总数量的自动计算
Vue.js 的computed
计算属性为我们提供了一种高效的方式来处理依赖数据变化的计算。totalPrice
计算属性通过reduce()
方法遍历goodsList
数组。在遍历过程中,它将每个商品的价格price
乘以数量num
,并将所有结果累加起来,得到购物车的总价。最后,使用toFixed(2)
方法将总价保留两位小数,确保价格显示的准确性。
// 计算总价
const totalPrice = computed(() => {
return goodsList.reduce((sum, item) => sum + (item.price * item.num), 0);
});
total
计算属性同样使用reduce()
方法,它遍历goodsList
数组,将每个商品的数量num
累加起来,得到购物车中商品的总数量。计算属性具有缓存机制,只有当依赖的数据(即goodsList
中的商品信息)发生变化时,才会重新计算,大大提高了性能。
// 计算总数量
const total = computed(() => {
return goodsList.reduce((sum, item) => sum + item.num, 0);
});
(四)商品添加与编辑功能
- 添加商品流程:当用户点击 “添加” 按钮时,
addGoods()
函数被调用。该函数首先将showEdit
变量设置为true
,这会通过v - show
指令使添加商品的输入框区域显示在页面上。同时,将editingIndex
设为-1
,表示当前处于添加新商品的模式。然后,清空newGoods
对象的属性值,以便用户输入新商品的信息。
// 点击显示添加商品的输入框
function addGoods() {
showEdit.value = true;
editingIndex.value = -1;
newGoods.name = '';
newGoods.price = '';
newGoods.num = '';
}
当用户在输入框中填写完商品名称、价格和数量后,点击 “确定” 按钮,sure_edit()
函数开始执行。该函数首先验证用户是否填写了所有必要的信息(即newGoods.name
、newGoods.price
和newGoods.num
都有值)。如果处于添加模式(editingIndex.value < 0
),则将newGoods
对象作为一个新的商品项添加到goodsList
数组中,然后将showEdit
设为false
,隐藏输入框区域,完成新商品的添加过程。
// 点击确定按钮添加商品
function sure_edit() {
if (newGoods.name && newGoods.price && newGoods.num) {
if (editingIndex.value >= 0) {
// 编辑模式 - 更新现有商品
goodsList[editingIndex.value] = { ...newGoods };
} else {
// 添加模式 - 添加新商品
goodsList.push({ ...newGoods });
}
showEdit.value = false;
}
}
- 编辑商品流程:当用户点击商品操作栏中的 “编辑” 按钮时,
editGoods(index)
函数被触发。该函数将showEdit
设为true
,显示输入框区域,并将editingIndex
设为当前商品的下标,表明进入编辑模式。同时,将当前商品的名称、价格和数量信息从goodsList
中提取出来,填充到newGoods
对象中,这样用户在输入框中看到的就是当前商品的现有信息,可以直接进行修改。
// 通过下标只编辑对应的商品
function editGoods(index) {
showEdit.value = true;
editingIndex.value = index;
newGoods.name = goodsList[index].name;
newGoods.price = goodsList[index].price;
newGoods.num = goodsList[index].num;
}
用户修改完信息后点击 “确定” 按钮,sure_edit()
函数再次发挥作用。由于此时editingIndex.value >= 0
,处于编辑模式,函数会用newGoods
对象的新值替换goodsList
中对应下标的商品项,实现商品信息的编辑更新,然后隐藏输入框区域。
(五)输入验证
为了确保用户输入的商品价格和数量是有效的数字,我们编写了NumberInput(event)
函数。该函数获取输入框的当前值event.target.value
,然后使用正则表达式/[^0 - 9.]/g
匹配输入值中除数字和小数点以外的字符,并将这些字符替换为空字符串。这样,无论用户输入什么内容,最终输入框中只会保留有效的数字和小数点,避免了因用户误输入导致的计算错误或程序异常,提高了系统的稳定性和用户体验。
// 验证输入是否为数字和小数点
function NumberInput(event) {
const value = event.target.value;
event.target.value = value.replace(/[^0 - 9.]/g, '');
}
最后,通过return
语句将所有需要在模板中使用的数据和函数暴露出去,以便 Vue.js 能够在页面上正确地渲染和响应用户操作。
return {
goodsList,
newGoods,
totalPrice,
total,
removeGoods,
add_num,
reduce_num,
addGoods,
showEdit,
close_edit,
editGoods,
sure_edit,
NumberInput
}
通过以上详细的步骤,我们成功地利用 Vue.js 构建了一个基础购物车系统。从项目的初始化、HTML 结构搭建、CSS 样式美化到 Vue.js 核心逻辑的实现,每个环节都紧密配合,展示了 Vue.js 在前端开发中的强大功能和便捷性。希望这篇文章能为你的前端开发学习和实践提供有价值的参考,帮助你在开发电商相关项目时更加得心应手。