用 Vue.js 构建基础购物车:从 0 到 1 的实战解析

发布于:2025-04-15 ⋅ 阅读:(25) ⋅ 点赞:(0)

在当今数字化购物的浪潮中,购物车功能已成为电商平台不可或缺的一部分。它不仅承担着记录用户所选商品的重任,还需提供流畅的交互体验和精准的计算逻辑。本文将深入探讨如何利用 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
}]);

(二)商品操作功能实现

  1. 删除商品removeGoods(index)函数负责从goodsList数组中删除指定下标的商品项。它使用 JavaScript 数组的splice()方法,该方法会改变原数组。当用户点击商品操作栏中的 “删除” 按钮时,对应的商品下标会作为参数传递给这个函数,从而实现商品的删除操作,并且页面会自动刷新以反映这一变化。
// 删除商品
function removeGoods(index) {
    goodsList.splice(index, 1);
}
  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);
});

(四)商品添加与编辑功能

  1. 添加商品流程:当用户点击 “添加” 按钮时,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.namenewGoods.pricenewGoods.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;
    }
}
  1. 编辑商品流程:当用户点击商品操作栏中的 “编辑” 按钮时,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 在前端开发中的强大功能和便捷性。希望这篇文章能为你的前端开发学习和实践提供有价值的参考,帮助你在开发电商相关项目时更加得心应手。