购物车——js小项目实例

article/2025/1/9 17:10:33

购物车——js小项目实例

      • 首先构思好整体样式
    • 添加点击事件
      • 🍁事件委托
      • 🍁接下来就是各种函数的书写
    • 最后附上完整js代码

短短几周,js阶段的学习已然结束,结课作业就是实现一个购物车功能

功能:

1、可以添加商品
2、全选按钮
3、合计
4、数量增减

以上。

先看看成品图
在这里插入图片描述









🍁自在飞花轻似梦,无边丝雨细如愁。 —— 浣溪沙·漠漠轻寒上小楼🍁

首先构思好整体样式

在这里插入图片描述

HTML

<!-- 作业专用html框架 -->
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>购物车</title><link rel="stylesheet" href="./css/reset.css"><link rel="stylesheet" href="./css/index.css"><link rel="shortcut icon" href="/icon/icon.png" type="image/x-icon">
</head><body><div id="app"><div class="framework"><header><nav><ul class="headbar"><li><span>/</span><a href="#">我的购物车</a>/</li></ul></nav></header><main><div class="container"><div class="title"><span id="realname">商品名称:</span><input type="text" id="productName" value=""><span>商品价格:</span><!-- 正则表达式,只能输入数字,且为正值 --><input type="text" id="productPrice" pattern="[0-9]*"><button id="cartBtn">加入购物车</button></div><div class="content"><ul><li class="listTitle"><input type="checkbox" class="checkbox" id="allCombo"><!-- 全选按钮,让其脱离文档流 --><span class="float">全选按钮</span><span>商品名称</span><span>商品价格</span><span>数量</span><span>操作</span></li></ul><ul id="contentBox"></ul><!-- 添加 --></div><div class="info"><span class="allProducts"></span><button id="buttonClear">清空购物车</button></div></div></main><footer></footer></div></div>
</body>
<script src="./js/index.js"></script></html>

CSS

body {background-color: rgb(41, 42, 45);
}header {width: 100%;height: 50px;background-color: rgb(240, 240, 240);position: fixed;top: 0;
}
.headbar{float: right;height: inherit;line-height: 50px;margin-right: 40px;
}
.headbar li a{font-size: 14px;color: rgb(54,54,55);margin: 0 20px;
}
main {margin: 0 auto;width: 1200px;min-height: 100vh;background-color: rgb(234, 67, 53);padding: 120px 0;
}.title {background-color: rgba(255,255,255,.85);margin: 0 20px 25px;padding: 15px 10px;font-size: 20px;line-height: 45px;border-radius: 10px;
}.title input {width: 300px;height: 45px;vertical-align: middle;
}.title button {width: 180px;height: 40px;border: none;font-size: 18px;vertical-align: middle;background-color: rgb(221, 221, 221);
}.content,
.info {background-color: #fff;margin: 0 20px 15px;padding: 15px 10px;font-size: 20px;position: relative;border-radius: 10px;background-color: rgba(255,255,255,.85);
}.info {position: fixed;bottom: 20px;width: 1155px;
}.float {position: absolute;left: 150px;
}.content li {display: grid;grid-template-columns: 1fr 1fr 1fr 1fr 1fr;vertical-align: middle;border-bottom: 1px solid rgb(204, 204, 204);padding: 15px 0;line-height: 33px;
}li input,
#checkbox {height: 14px;margin: auto 0;cursor: pointer;}#del {cursor: pointer;
}li span {text-align: center;
}.singleNum {outline: none;width: 80px;height: 25px;vertical-align: middle;margin: 0 5px;
}#minus,
#plus {width: 20px;height: 20px;font-size: 18px;border: none;background-color: inherit;cursor: pointer;
}.info button {border: none;font-size: 20px;background-color: inherit;
}input:invalid {animation: floa .4s;
}@keyframes floa {0% {transform: translateX(0px);background-color: inherit;}20% {transform: translateX(20px);background-color: red;}40% {transform: translateX(0px);background-color: red;}60% {transform: translateX(-20px);background-color: red;}80% {transform: translateX(0px);background-color: red;}100% {transform: translateX(0px);background-color: inherit;}
}

这样一个静态页面就算完成了

接下来,小生要进行页面逻辑的编写了

新建一个类
class cart {}
var cartObj = new cart();
在类中添加数据,事件函数,功能函数,变量合集
class cart {goods = [];
}
//将原型引用到实例
var cartObj = new cart();

小生先在Goods中添加一些数据,方便测试开大

class cart {goods = [{id:1,realname:'iPhone14 Pro Max',price:9999,num:1,checked:false},{id:2,realname:'iPhone14 Pro',price:8999,num:1,checked:false},{id:3,realname:'iPhone14 Max',price:6799,num:1,checked:false},{id:4,realname:'iPhone14 Pro Max',price:5999,num:1,checked:false},];
}
var cartObj = new cart();
然后是将数据渲染到页面里,这里小生是遍历一遍数据,然后用字符串拼接,将数据加到页面中
    // 渲染到页面render() {var str = ''for (let i = 0; i < this.goods.length; i++) {str = str + '<li id="' + this.goods[i].id + '">';str = str + '<input type="checkbox" name="" id="checkbox" ' + (this.goods[i].checked ? 'checked' : '') + '>';str = str + '<span>' + this.goods[i].realname + '</span>';str = str + '<span><em id="singlePrice">' + this.goods[i].price + '</em> 元</span>';str = str + '<span><button id="minus">-</button><input class="singleNum" readonly="" id="singleNum" type="text" value="' + this.goods[i].num + '"><button id="plus">+</button></span>';str = str + '<span ' + 'id="del" ' + '>删除</span>';str = str + '</li>';}var str2 = ''str2 = str2 + '共计' + this.inTotal() + '种商品,合计' + this.inTotalSum() + '元。';this.contentBox.innerHTML = strthis.allProducts.innerHTML = str2localStorage.setItem('goods', JSON.stringify(this.goods));}

在这里插入图片描述

接下来就是实现一些基础功能

添加点击事件

🍁事件委托

对于“对于事件处理程序过多”,问题的解决方案就是事件委托。事件委托利用了事件冒泡,只指定一个事件处理程序,就可以管理某一类型的事件。
使用事件委托,只需要在DOM树中尽量最高的层次上添加一个事件处理程序

例如接下来的点击事件,有增减数量按钮,删除按钮,选中按钮,全选按钮

小生习惯将事件函数都归类在一起。

首先建立一个事件函数

    addevent() {//用来添加点击事件};

给购物车按钮添加点击事件

要注意this的指向,弄明白闭包的思想

   addevent() {var _this = this;//闭包//购物车按钮添加点击事件this.cartBtn.addEventListener('click', function () {if (!isNaN(_this.productPrice.value) && _this.productPrice.value > 0) {_this.add()//执行添加函数}});};

添加全选按钮事件

   addevent() {//其他代码// 全选事件this.allCombo.addEventListener('click', function (e) {_this.selectAll();});};

接下来是内容区的点击事件,由于比较多,就可以用委派的思想

通过 e.target.id,再配合switch,很方便的实现委派思想

   addevent() {//其他代码this.contentBox.addEventListener('click', function (e) {switch (e.target.id) {// 单击删除按钮case 'del':console.log('del', e.target.parentNode.id)_this.del(e.target.parentNode.id);break;//全选对应全选case 'checkbox':// console.log('dian',e.target.parentNode.id);_this.exchangeCheckbox(e.target.parentNode.id);break;//减case 'minus':console.log('dian', e.target.parentNode.parentNode.id);_this.decrease(e.target.parentNode.parentNode.id);break;case 'plus':console.log('dian', e.target);_this.increase(e.target.parentNode.parentNode.id);break;// case 'singleNum'://     console.log(e.target.onblur)//     break;default:break;}});};

🍁接下来就是各种函数的书写

添加数据

    //添加数据add() {var cache = {id: new Date().getTime() + String(Math.floor(Math.random() * 10)),realname: this.productName.value,price: this.productPrice.value,num: 1,checked: this.allCombo.checked,}this.goods.unshift(cache);this.render();}

删除数据函数

    //删除函数del(id) {for (let i = 0; i < this.goods.length; i++) {if (id == this.goods[i].id) {this.goods.splice(i, 1)}}this.render();};

清空购物车函数

    // 清空函数clear() {this.goods = [];this.allCombo.checked = false;this.render();};

全选按钮函数

    //全选函数selectAll() {for (let i = 0; i < this.goods.length; i++) {this.goods[i].checked = allCombo.checked;}this.render();};//对应函数exchangeCheckbox(id) {for (let i = 0; i < this.goods.length; i++) {if (id == this.goods[i].id) {this.goods[i].checked = !this.goods[i].checked;}}let flag = true;for (let j = 0; j < this.goods.length; j++) {if (!this.goods[j].checked) {flag = false;}this.allCombo.checked = flag;this.render();}};

增减数量按钮

    // 减decrease(index) {for (let i = 0; i < this.goods.length; i++) {if (index == this.goods[i].id) {if (this.goods[i].num > 1) {this.goods[i].num--;}console.log(this.goods[i].num);}}this.render();};increase(index) {for (let i = 0; i < this.goods.length; i++) {if (index == this.goods[i].id) {this.goods[i].num++;console.log(this.goods[i].num);}}this.render();};

计算合计

    // 计算价格inTotal() {var num = 0;for (let i = 0; i < this.goods.length; i++) {if (this.goods[i].checked) {num++;}}return num;};inTotalSum() {var sum = 0var sumAll = 0;for (let i = 0; i < this.goods.length; i++) {if (this.goods[i].checked) {sum = this.goods[i].price * this.goods[i].num;}sumAll += sum;}return sumAll;};

这样大部分业务逻辑就算完成了

还有些细节需要完成

添加构造函数,将数据存储在本地

class cart {//商品数据代码//构造函数constructor() {if (localStorage.getItem('goods')) {this.goods = JSON.parse(localStorage.getItem('goods'));}this.render(); //渲染this.addevent();//事件函数在运行}//事件代码//函数代码
}

在这里插入图片描述

最后附上完整js代码

class cart {//建立一个数组goods = [];//构造函数constructor() {if (localStorage.getItem('goods')) {this.goods = JSON.parse(localStorage.getItem('goods'));}this.render(); //渲染this.addevent();//事件函数在运行}cartBtn = document.getElementById('cartBtn');//获取加入购物车的按钮productName = document.getElementById('productName');//获取页面中商品名称productPrice = document.getElementById('productPrice');//获取页面中商品价格contentBox = document.getElementById('contentBox');//获取页面中内容的盒子buttonClear = document.getElementById('buttonClear');// 获取页面中清空购物车的盒子allProducts = document.querySelector('.allProducts')//获取页面中的统计信息allCombo = document.getElementById('allCombo');// 全选按钮//事件归类addevent() {var _this = this;//闭包//购物车按钮添加点击事件this.cartBtn.addEventListener('click', function () {if (!isNaN(_this.productPrice.value) && _this.productPrice.value > 0) {_this.add()//执行添加函数}});// 全选事件this.allCombo.addEventListener('click', function (e) {// console.log(e.target)_this.selectAll();});this.contentBox.addEventListener('click', function (e) {switch (e.target.id) {// 单击删除按钮case 'del':console.log('del', e.target.parentNode.id)_this.del(e.target.parentNode.id);break;//全选对应全选case 'checkbox':// console.log('dian',e.target.parentNode.id);_this.exchangeCheckbox(e.target.parentNode.id);break;//减case 'minus':console.log('dian', e.target.parentNode.parentNode.id);_this.decrease(e.target.parentNode.parentNode.id);break;case 'plus':console.log('dian', e.target);_this.increase(e.target.parentNode.parentNode.id);break;// case 'singleNum'://     console.log(e.target.onblur)//     break;default:break;}});//点击清空购物车this.buttonClear.addEventListener('click', function () {_this.clear();});};//添加数据add() {var cache = {id: new Date().getTime() + String(Math.floor(Math.random() * 10)),realname: this.productName.value,price: this.productPrice.value,num: 1,checked: this.allCombo.checked,}this.goods.unshift(cache);this.render();}//删除函数del(id) {for (let i = 0; i < this.goods.length; i++) {if (id == this.goods[i].id) {this.goods.splice(i, 1)}}this.render();};// 清空函数clear() {this.goods = [];this.allCombo.checked = false;this.render();};//全选函数selectAll() {for (let i = 0; i < this.goods.length; i++) {this.goods[i].checked = allCombo.checked;}this.render();};//对应函数exchangeCheckbox(id) {for (let i = 0; i < this.goods.length; i++) {if (id == this.goods[i].id) {this.goods[i].checked = !this.goods[i].checked;}}let flag = true;for (let j = 0; j < this.goods.length; j++) {if (!this.goods[j].checked) {flag = false;}this.allCombo.checked = flag;this.render();}};// 减decrease(index) {for (let i = 0; i < this.goods.length; i++) {if (index == this.goods[i].id) {if (this.goods[i].num > 1) {this.goods[i].num--;}console.log(this.goods[i].num);}}this.render();};increase(index) {for (let i = 0; i < this.goods.length; i++) {if (index == this.goods[i].id) {this.goods[i].num++;console.log(this.goods[i].num);}}this.render();};// 计算价格inTotal() {var num = 0;for (let i = 0; i < this.goods.length; i++) {if (this.goods[i].checked) {num++;}}return num;};inTotalSum() {var sum = 0var sumAll = 0;for (let i = 0; i < this.goods.length; i++) {if (this.goods[i].checked) {sum = this.goods[i].price * this.goods[i].num;}sumAll += sum;}return sumAll;};// 渲染到页面render() {var str = ''for (let i = 0; i < this.goods.length; i++) {str = str + '<li id="' + this.goods[i].id + '">';str = str + '<input type="checkbox" name="" id="checkbox" ' + (this.goods[i].checked ? 'checked' : '') + '>';str = str + '<span>' + this.goods[i].realname + '</span>';str = str + '<span><em id="singlePrice">' + this.goods[i].price + '</em> 元</span>';str = str + '<span><button id="minus">-</button><input class="singleNum" readonly="" id="singleNum" type="text" value="' + this.goods[i].num + '"><button id="plus">+</button></span>';str = str + '<span ' + 'id="del" ' + '>删除</span>';str = str + '</li>';}var str2 = ''str2 = str2 + '共计' + this.inTotal() + '种商品,合计' + this.inTotalSum() + '元。';this.contentBox.innerHTML = strthis.allProducts.innerHTML = str2localStorage.setItem('goods', JSON.stringify(this.goods));}
}var cartObj = new cart();

http://chatgpt.dhexx.cn/article/vRDRXEYq.shtml

相关文章

SpringBoot+Vue项目实例开发及部署

目录 一、SpringBoot快速上手 1、SpringBoot介绍 2、SpringBoot特点 3、快速创建SpringBoot应用 4、SpringBoot开发热部署 二、Web开发基础 1、Web入门 2、控制器 3、路由映射 4、参数传递 三、Web开发进阶 1、静态资源访问 2、文件上传原理 3、拦截器 四、构建…

微信小程序项目实例——手势解锁

微信小程序项目实例——手势解锁 文章目录 微信小程序项目实例——手势解锁一、项目展示二、设置手势、手势解锁三、手势重置文末&#xff1a;项目代码 项目代码见文字底部 一、项目展示 这是一款简单实用的手势解锁工具 手势解锁是当下常用的解锁方式 本实例以工具的形式 可以…

微信小程序项目实例——家居团购

微信小程序项目实例——家居团购 文章目录 微信小程序项目实例——家居团购一、项目展示二、首页三、购物车四、个人中心 项目代码见文字底部 一、项目展示 二、首页 首页由建材市场、团购活动、公益验房和线上拼团组成 从上到下分为广告区、导航区、内容区 核心代码如下&…

微信小程序项目实例——飞机大战

微信小程序项目实例——飞机大战 文章目录 微信小程序项目实例——飞机大战一、项目展示二、设计介绍三、总结 项目代码见文字底部&#xff0c;点赞关注有惊喜 一、项目展示 二、设计介绍 游戏和传统的飞机大战模式一样 这里设置了三种敌机和自家飞机的受损图 同时游戏设计了道…

微信小程序项目实例——双人五子棋

微信小程序项目实例——双人五子棋 文章目录 微信小程序项目实例——双人五子棋一、项目展示二、项目核心代码三、效果展示文末 项目代码见文字底部&#xff0c;点赞关注有惊喜 一、项目展示 微信小程序项目实例——双人五子棋 双人五子棋是一款游戏小程序 两位选手可以在15x1…

Android开发之项目实例(登录,注册)

Android开发 实现登录注册界面 前言&#xff1a; 今天项目刚刚做完&#xff0c;我就迫不急待的想分享一下&#xff0c;自己通过实例项目踩过的坑以及遇到遇到的困难发表一下&#xff0c;以便刚刚接触的伙伴跳跳坑&#xff0c;也便于自己在今后的开发中巩固&#xff0c;此篇文…

Django新手项目实例

1. 程序安装 &#xff08;1&#xff09;安装Django&#xff1a; pip3 install django&#xff08;2&#xff09;配置系统环境 成功安装Django后&#xff0c;在python目录script路径可找到django-admin.exe文件&#xff0c;将它加入操作系统环境变量中。这样以后调用会比较方便…

微信小程序项目实例——印记

微信小程序项目实例——印记 文章目录 微信小程序项目实例——印记一、项目展示二、日记列表三、日记发布文末 项目代码见文字底部&#xff0c;点赞关注有惊喜 一、项目展示 印记是一款简洁便利的日记本&#xff0c;用户可以在其中发布自己的日记本&#xff0c;同时也可以查看…

微信小程序项目实例——备忘录

微信小程序项目实例——备忘录 文章目录 微信小程序项目实例——备忘录一、项目展示二、项目介绍三、核心代码 项目代码见文字底部&#xff0c;点赞关注有惊喜 一、项目展示 二、项目介绍 项目是一个备忘录&#xff0c;拥有记录文字、计时和提醒的基本功能 项目只有一个页面&…

微信小程序项目实例——幸运大转盘

微信小程序项目实例——幸运大转盘 文章目录 微信小程序项目实例——幸运大转盘一、项目展示二、抽奖页三、领奖页文末&#xff1a;项目代码 项目代码见文字底部&#xff0c;点赞关注有惊喜 一、项目展示 幸运大转盘是一个简单的抽奖小程序 参与用户点击抽奖便可抽取轮盘的奖品…

微信小程序项目实例——狼人杀

微信小程序项目实例——狼人杀 文章目录 微信小程序项目实例——狼人杀一、项目展示二、首页三、游戏页四、特殊角色文末 项目代码见文字底部&#xff0c;点赞关注有惊喜 一、项目展示 狼人杀是一款多人参与的&#xff0c;通过语言描述推动、较量口才和分析判断能力的策略类桌…

project实操——项目实例

1. 新建项目 2. 设置项目日历 可以设置每周工作几天&#xff0c;每天工作几小时 点击 项目 -> 更改工作时间 在弹出窗口上&#xff0c;选择下方的“”工作周“选项卡&#xff0c;点击右侧的【详细信息】按钮 系统打开的详细信息窗口上&#xff0c; 选中左侧列表中的“周六…

Android Studio同步远程Git代码到本地

前一篇文件说如何将本地代码同步到远程Git服务器&#xff08;将代码同步到远程Git服务器&#xff09;&#xff0c;这篇说说如何在Android Studio中将远程代码同步到本地。 环境说明&#xff1a; 1、本地需要安装有git环境 2、Android Studio 3、存放项目的远程服务器地址&a…

git 同步远程和本地的同名分支

首先正常创建一个本地仓库&#xff0c;添加内容&#xff0c;跟远程关联 git init git add . git commit -m "" git remote add origin 远程仓库地址 如果在本地创建了一个新的分支 git checkout -b branch_one 然后将该分支直接推动到远程进行同步 git push -u …

使用git 实现本地文件和远程代码仓的互相同步

一、关于Git的安装与配置&#xff0c;可以参考这两篇文章 Git 详细安装教程&#xff08;详解 Git 安装过程的每一个步骤&#xff09; GitHub的安装与配置 二、同步本地文件与代码仓常规流程 1、在github上创建项目2、使用git clone https://github.com/xxxxxxx/xxxxx.git 克…

git(实现代码存档和同步)

远程仓库就是github&#xff0c;码云这些之类的&#xff0c;所有人都以远程仓库的文件作为最新版本 每个人都有自己的工作区&#xff08;本地电脑里面的一个文件夹&#xff09;&#xff0c;每个人都可以用clone把最新版本的文件复制到本地 比如我现在有四个文件&#xff0c;但…

[Git] 本地代码库和远程同步

一 前言 这本来不是一个很严重的问题, 有很多办法可以处理, 但是对于Git新手来说, 会觉得非常可怕, 因为不知道怎么恢复之前的状态, 不知道当前状态上传上去会造成什么影响, 最怕的是影响到master之类的主分支, 然后把别人的工作搞丢, 那就完蛋了. 我刚开始接触Git的时候, 上…

git操作之同步代码到仓库

1、先创建一个仓库&#xff0c;然后把创建的空仓库克隆到本地&#xff1b;2、把程序拷贝到本地的仓库中&#xff0c;然后再进行下列操作&#xff1b;&#xff08;1&#xff09;git add . 保存全部内容&#xff08;2&#xff09;git commit -m "项目描述"(3) git pu…

如何将git服务器同步到本地文件夹,使用git在服务器上部署git仓库并实现提交代码时同步代码到生产环境...

最近由于需要对正在运行的系统进行新功能添加&#xff0c;本来是可以通过github进行代码维护&#xff0c;但是由于这个项目涉及一些问题&#xff0c;目前还不能开源&#xff0c;所以只能是手动覆盖bug文件&#xff0c;生产环境上的代码反而是最新的了。 之前有个思路&#xff0…

git 项目代码上传到服务器上,git 上传代码到服务器

一、建立本地git仓库 1、cd到你项目根目录下 git init 二、将本地所有文件添加到暂存区 git add . . 表示所有文件 如果想添加项目中的指定文件,那就把.改为指定文件名或者目录即可,多个目录用空格隔开 三、将暂存区的文件提交到本地仓库 git commit -m 注释 四、在码云上创建…