Web前端—(原生JS)购物车效果

目录

  • 购物车效果
    • 分析数据
      • 单件商品的数据
      • 整个界面的数据
    • 分析界面
    • 分析事件

购物车效果

在这里插入图片描述

先准备好原始数据和素材
在下面数据的基础上,编写index.js
在这里插入图片描述

分析数据

  • 编写程序要从数据入手,从数据到界面最后到事件
  • 在分析数据的过程中,要分析数据是通过属性出现还是通过方法出现

单件商品的数据

  • 我们观察data.js中的数据:商品数组goods

    • pic:图片
    • title:标题
    • desc:描述
    • sellNumber:月售
    • favorRate:好评率
    • price:价格
  • 为了避免改变原始数据。我们创建一个单件商品的数据的类(class)
    在这里插入图片描述

  • 代码如下:
// 单件商品的数据
class UIGoods{constructor(g){this.data = g;this.choose = 0; // 每件商品被选中的数量}// 获取商品的总价getTotalPrice(){return this.data.price * this.choose;}// 是否选中此商品isChoose(){return this.choose > 0;}// 商品选择数量+1increase(){this.choose++;}// 商品选择数量-1decrease(){this.choose--;}}
  • 对这个类进行测试 var uig = new UIGoods(goods[0]);
  • 测试成功进行下一步在这里插入图片描述

整个界面的数据

分析整个页面需要用到的数据,创建UIData类,并进行测试(大家可以自行在控制台进行测试)
在这里插入图片描述

  • 代码如下
// 整个界面的数据
class UIData{constructor(){var uiGoods = [];for(let i=0; i<goods.length; i++){let uig = new UIGoods(goods[i]);uiGoods.push(uig);}this.uiGoods = uiGoods;this.deliveryThreshold = 30; //起送费this.deliverPrice = 5; //配送费}// 获取总价getTotalPrice(){var sum = 0;for(let i=0; i<this.uiGoods.length; i++){let g = this.uiGoods[i];sum += g.getTotalPrice();}return sum;}// 增加某件商品的数量increase(index){this.uiGoods[index].increase();}// 减少某件商品的数量decrease(index){this.uiGoods[index].decrease();}// 得到总共的选中数量getTotalChooseNumber(){var sum = 0;for(let i=0; i<this.uiGoods.length; i++){sum += this.uiGoods[i].choose;}return sum;}// 判断购物车中有没有商品hasGoodsInCar(){return this.getTotalChooseNumber() > 0;}// 判断是否跨过了配送标准isCrossDeliveryThreshold(){return this.getTotalPrice() >= this.deliveryThreshold;}// 判断该商品是否被选中isChoose(index){return this.uiGoods[index].isChoose();}}

分析界面

在分析完数据逻辑之后,我们来分析界面之间的逻辑关系
创建一个UI类

  • 代码如下:
// 整个界面
class UI{constructor(){this.uiData = new UIData();this.doms = {goodsContainer:document.querySelector('.goods-list'),deliverPrice:document.querySelector('.footer-car-tip'),footerPay:document.querySelector('.footer-pay'),footerPayInnerSpan:document.querySelector('.footer-pay span'),totalPrice:document.querySelector('.footer-car-total'),car:document.querySelector('.footer-car'),badge:document.querySelector('.footer-car-badge')}var carRect = this.doms.car.getBoundingClientRect();var jumpTarget = {x: carRect.left + carRect.width / 2,y: carRect.top + carRect.height / 5,};this.jumpTarget = jumpTarget;this.createHTML();this.updateFooter();this.listenEvent();}// 监听各种事件listenEvent(){this.doms.car.addEventListener('animationend', function(){this.classList.remove('animate');});}// 根据商品数据,创建商品列表createHTML(){// 1. 生成html字符串(parse html) 执行效率低,开发效率高// 2. 一个一个创建元素 执行效率高,开发效率低// 这里我们采用第一种方式var html = '';for(let i=0; i<this.uiData.uiGoods.length; i++){var g = this.uiData.uiGoods[i];html += `<div class="goods-item"><img src="${g.data.pic}" alt="" class="goods-pic" /><div class="goods-info"><h2 class="goods-title">${g.data.title}</h2><p class="goods-desc">${g.data.desc}</p><p class="goods-sell"><span>月售 ${g.data.sellNumber}</span><span>好评率${g.data.favorRate}</span></p><div class="goods-confirm"><p class="goods-price"><span class="goods-price-unit">¥</span><span>${g.data.price}</span></p><div class="goods-btns"><i index="${i}" class="iconfont i-jianhao"></i><span>${g.choose}</span><i index="${i}" class="iconfont i-jiajianzujianjiahao"></i></div></div></div></div>`;}this.doms.goodsContainer.innerHTML = html;}// 界面的增加减少increase(index){this.uiData.increase(index);this.updateGoodsItem(index);this.updateFooter();this.jump(index);}decrease(index){this.uiData.decrease(index);this.updateGoodsItem(index);this.updateFooter();}// 更新某个商品元素的显示状态updateGoodsItem(index){var goodsDom = this.doms.goodsContainer.children[index];if(this.uiData.isChoose(index)){goodsDom.classList.add('active');}else{goodsDom.classList.remove('active');}var span = goodsDom.querySelector('.goods-btns span');span.textContent = this.uiData.uiGoods[index].choose;}// 更新页脚updateFooter(){var total = this.uiData.getTotalPrice(); this.doms.deliverPrice.textContent = `配送费¥${this.uiData.deliverPrice}`;if(this.uiData.isCrossDeliveryThreshold()){// 到达起送点this.doms.footerPay.classList.add('active');}else{this.doms.footerPay.classList.remove('active');// 更新还差多少钱var dis = this.uiData.deliveryThreshold - total;dis = Math.round(dis); this.doms.footerPayInnerSpan.textContent = `还差¥${dis}元起送`;}// 总价元素,设置总价this.doms.totalPrice.textContent = total.toFixed(2);// 设置购物车的样式状态if(this.uiData.hasGoodsInCar()){this.doms.car.classList.add('active');}else{this.doms.car.classList.remove('active');}// 设置购物车中的数量this.doms.badge.textContent = this.uiData.getTotalChooseNumber();}// 购物车动画carAnimate(){this.doms.car.classList.add('animate');}// 抛物线跳跃的元素jump(index){// 找到对应商品的加号var btnAdd = this.doms.goodsContainer.children[index].querySelector('.i-jiajianzujianjiahao');var rect = btnAdd.getBoundingClientRect();var start = {x:rect.left,y:rect.top};// 跳var div = document.createElement('div');div.className = 'add-to-car';var i = document.createElement('i');i.className = 'iconfont i-jiajianzujianjiahao';// 设置初始位置div.style.transform = `translateX(${start.x}px)`;i.style.transform = `translateY(${start.y}px)`;div.appendChild(i);document.body.appendChild(div);// 强行渲染div.clientWidth;// 设置结束位置div.style.transform = `translateX(${this.jumpTarget.x}px)`;i.style.transform = `translateY(${this.jumpTarget.y}px)`;var that = this;div.addEventListener('transitionend',function () {div.remove();that.carAnimate();},{once: true, // 事件仅触发一次});}}

分析事件

到这里为止界面上的逻辑已经全部完成,开始添加事件
在这里,为了获取我们到底是点击了哪个,可以添加一个自定义属性来获取index

  • 代码如下
var ui = new UI();// 事件
ui.doms.goodsContainer.addEventListener('click', function (e) {if (e.target.classList.contains('i-jiajianzujianjiahao')) {var index = +e.target.getAttribute('index');ui.increase(index);} else if (e.target.classList.contains('i-jianhao')) {var index = +e.target.getAttribute('index');ui.decrease(index);}});window.addEventListener('keypress', function (e) {if (e.code === 'Equal') {ui.increase(0);} else if (e.code === 'Minus') {ui.decrease(0);}});

到这里,就实现了购物车的全部效果,我会上传我的资源,大家自行下载。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/790878.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

HarmonyOS NEXT应用开发之@Provide装饰器和\@Consume装饰器:与后代组件双向同步

Provide和Consume&#xff0c;应用于与后代组件的双向数据同步&#xff0c;应用于状态数据在多个层级之间传递的场景。不同于上文提到的父子组件之间通过命名参数机制传递&#xff0c;Provide和Consume摆脱参数传递机制的束缚&#xff0c;实现跨层级传递。 其中Provide装饰的变…

营销中的归因人工智能

Attribution AI in marketing 归因人工智能作为智能服务的一部分&#xff0c;是一种多渠道算法归因服务&#xff0c;根据特定结果计算客户互动的影响和增量影响。有了归因人工智能&#xff0c;营销人员可以通过了解每个客户互动对客户旅程每个阶段的影响来衡量和优化营销和广告…

x-cmd-pkg | broot 是基于 Rust 开发的一个终端文件管理器

简介 broot 是基于 Rust 开发的一个终端文件管理器&#xff0c;它设计用于帮助用户在终端中更轻松地管理文件和目录&#xff0c;使用树状视图探索文件层次结构、操作文件、启动操作以及定义您自己的快捷方式。 同时它还集成了 ls, tree, find, grep, du, fzf 等工具的常用功能…

Rredis缓存常见面试题

文章目录 1.什么是缓存穿透&#xff0c;怎么解决2.什么是缓存击穿&#xff0c;怎么解决3.什么是缓存雪崩&#xff0c;怎么解决4.双写一致性问题5.redisson添加的排他锁是如何保证读写、读读互斥的6.为什么不使用延迟双删7.redis做为缓存&#xff0c;数据的持久化是怎么做的8.re…

【信号处理】基于变分自编码器(VAE)的图片典型增强方法实现

关于 深度学习中&#xff0c;经常面临图片数据量较小的问题&#xff0c;此时&#xff0c;对数据进行增强&#xff0c;显得比较重要。传统的图片增强方法包括剪切&#xff0c;增加噪声&#xff0c;改变对比度等等方法&#xff0c;但是&#xff0c;对于后端任务的性能提升有限。…

ObjectiveC-08-OOP面向对象程序设计-类的分离与组合

本节用一简短的文章来说下是ObjectiveC中的类。类其实是OOP中的一个概念&#xff0c;概念上简单来讲类是它是一组关系密切属性的集合&#xff0c;所谓的关系就是对现实事物的抽象。 上面提到的关系包括很多种&#xff0c;比如has a&#xff0c; is a&#xff0c;has some等&…

小程序滑动删除组件+全选批量删除组件+附源码

小程序滑动删除组件全选批量删除组件附源码 说明 使用 uni-app、uview 组件开发&#xff0c;全端&#xff08;微信小程序、QQ小程序、抖音小程序等等&#xff09; 支持滑动删除组件、支持左滑删除、长按进入批量删除、全选删除、长按弹窗删除、 组件式开发&#xff0c;文章…

【VUE】ruoyi框架自带页面可正常缓存,新页面缓存无效

ruoyi框架自带页面可正常缓存&#xff0c;新页面缓存无效 背景&#xff1a; 用若依框架进行开发时&#xff0c;发现ruoyi自带的页面缓存正常&#xff0c;而新开发的页面即使设置了缓存&#xff0c;当重新进入页面时依旧刷新了接口。 原因&#xff1a;页面name与 getRouters …

外围极简便携式T12电烙铁(CH32X035)-第二篇

文章目录 系列文章目录前言一、pandas是什么&#xff1f;二、使用步骤 1.引入库2.读入数据总结 一、工程简介 原理图&#xff1a; PCB&#xff1a; 外壳&#xff1a; BOM&#xff1a; 二、功能模块介绍 1、 |----系统初始化 0&#xff1a;填写系统初值 …

OpenHarmony实战:Makefile方式组织编译的库移植

以yxml库为例&#xff0c;其移植过程如下文所示。 源码获取 从仓库获取yxml源码&#xff0c;其目录结构如下表&#xff1a; 表1 源码目录结构 名称描述yxml/bench/benchmark相关代码yxml/test/测试输入输出文件&#xff0c;及测试脚本yxml/Makefile编译组织文件yxml/.gitat…

水果销售(源码+文档)

水果销售管理系统&#xff08;小程序、ios、安卓都可部署&#xff09; 文件包含内容程序简要说明含有功能项目截图客户端添加地址首页商品详细意见反馈待发货商品分类我的代付款我的地址搜索防骗指南资料修改登录注册 后端管理分类管理反馈管理订单管理商品管理用户管理 文件包…

搜索与图论——拓扑排序

有向图的拓扑排序就是图的宽度优先遍历的一个应用 有向无环图一定存在拓扑序列&#xff08;有向无环图又被称为拓扑图&#xff09;&#xff0c;有向有环图一定不存在拓扑序列。无向图没有拓扑序列。 拓扑序列&#xff1a;将一个图排成拓扑序后&#xff0c;所有的边都是从前指…

C 字符串

在 C 语言中&#xff0c;字符串实际上是使用空字符 \0 结尾的一维字符数组。因此&#xff0c;\0 是用于标记字符串的结束。 空字符&#xff08;Null character&#xff09;又称结束符&#xff0c;缩写 NUL&#xff0c;是一个数值为 0 的控制字符&#xff0c;\0 是转义字符&…

CAD Plant3D 2023 下载地址及安装教程

CAD Plant3D是一款专业的三维工厂设计软件&#xff0c;用于在工业设备和管道设计领域进行建模和绘图。它是Autodesk公司旗下的AutoCAD系列产品之一&#xff0c;专门针对工艺、石油、化工、电力等行业的设计和工程项目。 CAD Plant3D提供了一套丰富的工具和功能&#xff0c;帮助…

计算机网络-HTTP相关知识-HTTP的发展

HTTP/1.1 特点&#xff1a; 简单&#xff1a;HTTP/1.1的报文格式包括头部和主体&#xff0c;头部信息是键值对的形式&#xff0c;使得其易于理解和使用。灵活和易于扩展&#xff1a;HTTP/1.1的请求方法、URL、状态码、头字段等都可以自定义和扩展&#xff0c;使得其具有很高的…

docker------docker入门

&#x1f388;个人主页&#xff1a;靓仔很忙i &#x1f4bb;B 站主页&#xff1a;&#x1f449;B站&#x1f448; &#x1f389;欢迎 &#x1f44d;点赞✍评论⭐收藏 &#x1f917;收录专栏&#xff1a;Linux &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#…

好用的Android Studio插件管理器

1.使用阿里云的通义灵码方便快速开发 1.1下载插件File->plugin->marketplace 搜索 Tongyilingma然后安装重启登录阿里云&#xff0c;确认 1.2 使用方法 输入信息描述 比如 //写一段冒泡排序然后换行&#xff0c;输入public/private/protected方法会自动生成联想代码…

机器学习——几个线性模型的简介

目录 形式 假设 一元回归例子理解最小二乘法 多元回归 广义线性回归 对数线性回归 逻辑回归 线性判别分析 形式 线性说白了就是初中的一次函数的一种应用&#xff0c;根据不同的(x,y)拟合出一条直线以预测&#xff0c;从而解决各种分类或回归问题&#xff0c;假设有 n …

03原理图:接口、无线、电机、STM32主控、整体模块化设计总结

接口部分 一、TTL 转 USB 驱动电路设计 方案很多&#xff0c;本设计采用的芯片是 CH340E 。 该芯片内部已经集成了振荡器&#xff0c;不需要外部增加晶振。如果其他型号的芯片内部没有振荡器&#xff0c;则外面需要加一个晶振。 再看这篇笔记的时候&#xff0c;你可能有点懵…

蓝桥杯第十三届电子类单片机组决赛程序设计

前言 一、决赛题目 1.比赛题目 2.题目解读 二、功能实现 1.关于定时器资源 1&#xff09;超声波和NE555需要的定时器资源 2&#xff09;定时器2 2.单位切换 3.数据长度不足时&#xff0c;高位熄灭 4.AD/DA多通道的处理 5.PWM输出 6.长按功能的实现 三、完整代码演…