Javascript实现购物车功能的详细代码


Posted in Javascript onMay 08, 2018

我们肯定都很熟悉商品购物车这一功能,每当我们在某宝某东上购买商品的时候,看中了哪件商品,就会加入购物车中,最后结算。购物车这一功能,方便消费者对商品进行管理,可以添加商品,删除商品,选中购物车中的某一项或几项商品,最后商品总价也会随着消费者的操作随着变化。

现在,笔者对购物车进行了简单实现,能够实现真实购物车当中的大部分功能。在本示例当中,用到了javascript中BOM操作,DOM操作,表格操作,cookie,json等知识点,同时,采用三层架构方式对购物车进行设计,对javascript的综合应用较强,对javascript初学者进阶有一定的益处。

请看主页效果图:

Javascript实现购物车功能的详细代码

现在读者已经对主页的效果图进行了了解,我在这里附上主页的html代码,供读者参考,建议读者根据自己的思路写代码。

请看html代码:

<!DOCTYPE html>
<html>

 <head>
 <meta charset="utf-8" />
 <title>商品列表页面</title>
 <!--商品列表样式表-->
 <link rel="stylesheet" type="text/css" href="../css/index.css" rel="external nofollow" />
 <!--cookie操作的js库-->
 <script src="../js/cookie.js" type="text/javascript" charset="utf-8"></script>
 </head>

 <body>
 <div class="container">
  <h1>商品列表</h1>
  <div class="mycar">
  <a href="cart.html" rel="external nofollow" >我的购物车</a><i id="ccount">0</i>
  </div>
  <div class="list">
  <dl pid="1001">
   <dt>
   <img src="../images/p1.jpg" />
   </dt>
   <dd>智能手表</dd>
   <dd>酷黑,棒,棒,棒,棒</dd>
   <dd>¥<span>998</span></dd>
   <dd>
   <button>添加购物车</button>
   </dd>
  </dl>
  <dl pid="1002">
   <dt>
   <img src="../images/p2.jpg" />
   </dt>
   <dd>智能手机001</dd>
   <dd>金红色,酷酷酷酷</dd>
   <dd>¥<span>1998</span></dd>
   <dd>
   <button>添加购物车</button>
   </dd>
  </dl>
  <dl pid="1003">
   <dt>
   <img src="../images/p3.jpg" />
   </dt>
   <dd>华为手机002</dd>
   <dd>帅帅帅帅帅帅帅帅帅帅</dd>
   <dd>¥<span>998</span></dd>
   <dd>
   <button>添加购物车</button>
   </dd>
  </dl>
  <dl pid="1004">
   <dt>
   <img src="../images/p4.jpg" />
   </dt>
   <dd>华为手机003</dd>
   <dd>杠杠的</dd>
   <dd>¥<span>2000</span></dd>
   <dd>
   <button>添加购物车</button>
   </dd>
  </dl>
  </div>
 </div>
 <!--
  描述:数据访问层,操作本地数据的模块
 -->
 <script type="text/javascript" src="../js/server.js"></script>
 <!--
  描述:本页面的js操作
 -->
 <script type="text/javascript" src="../js/index.js"></script>
 </body>
</html>

html结构代码有了之后,就可以对主页进行css表现设计,这里不对css进行过多讲解。

我们对主页进行设计之后,就可以进行与主页相关的DOM操作,涉及到添加按钮的点击事件,cookie和json的应用,cookie主要为了让当前数据与购物车进行共享,以方便操作。请看与之相关的javascript代码:

这是index.js代码,主要是主页的相关操作:

/*
 思路:
 第一步:获取所要操作的节点对象
 第二步:当页面加载完后,需要计算本地cookie存了多少【个】商品,把个数赋值给ccount
 第三步:为每一个商品对应的添加购物车按钮绑定一个点击事件onclick
  更改本地的cookie
  获取当前商品的pid
  循环遍历本地的cookie转换后的数组,取出每一个对象的pid进行对比,若相等则该商品不是第一次添加
  从购物车中取出该商品,然后更pCount值追加1
  否则:创建一个新的对象,保存到购物中。同时该商品的数量为1
 */

var ccount = document.getElementById("ccount"); //显示商品总数量的标签节点对象
var btns = document.querySelectorAll(".list dl dd button"); //所有的购物车按钮

//约定好用名称为datas的cookie来存放购物车里的数据信息 datas里所存放的就是一个json字符串
var listStr = cookieObj.get("datas");
/*判断一下本地是否有一个购物车(datas),没有的话,创建一个空的购物车,有的话就直接拿来使用*/
if(!listStr) { //没有购物车 datas json
 cookieObj.set({
 name: "datas",
 value: "[]"
 });
 listStr = cookieObj.get("datas");
}

var listObj = JSON.parse(listStr); //数组
/*循环遍历数组,获取每一个对象中的pCount值相加总和*/
var totalCount = 0; //默认为0
for(var i = 0, len = listObj.length; i < len; i++) {
 totalCount = listObj[i].pCount + totalCount;
}
ccount.innerHTML = totalCount;

/*循环为每一个按钮添加点击事件*/
for(var i = 0, len = btns.length; i < len; i++) {
 btns[i].onclick = function() {
 var dl = this.parentNode.parentNode;
 var pid = dl.getAttribute("pid");//获取自定义属性
 var arrs = dl.children;//获取所有子节点
 if(checkObjByPid(pid)) {
  listObj = updateObjById(pid, 1)
 } else {
  var imgSrc = arrs[0].firstElementChild.src;
  var pName = arrs[1].innerHTML;
  var pDesc = arrs[2].innerHTML;
  var price = arrs[3].firstElementChild.innerHTML;
  var obj = {
  pid: pid,
  pImg: imgSrc,
  pName: pName,
  pDesc: pDesc,
  price: price,
  pCount: 1
  };
  listObj.push(obj)
  listObj = updateData(listObj);
 }
 ccount.innerHTML = getTotalCount();
 }
}

这是cookie.js的代码,主要涉及cookie的设置获取操作,采用单例设计模式进行了封装设计,请看代码:

/*
 单例设计模式
 完整形式:[]中是可选项
 document.cookie = “name=value[;expires=date][;path=path-to-resource][;domain=域名][;secure]”
*/

var cookieObj = {
 /*
 增加或修改cookie
 参数:o 对象{}
 name:string cookie名
 value:string cookie值
 expires:Date对象 过期时间
 path:string 路径限制
 domain:string 域名限制
 secure:boolean true https false或undeinfed 
 */
 set: function(o) {
 var cookieStr = encodeURIComponent(o.name) + "=" + encodeURIComponent(o.value);
 if(o.expires) {
  cookieStr += ";expires=" + o.expires;
 }
 if(o.path) {
  cookieStr += ";path=" + o.path;
 }
 if(o.domain) {
  cookieStr += ";domain=" + o.domain;
 }
 if(o.secure) {
  cookieStr += ";secure";
 }

 document.cookie = cookieStr;
 },
 /*
 删除
 参数:n string cookie的名字
 */
 del: function(n) {
 var date = new Date();
 date.setHours(-1);
 //this代表的是当前函数的对象
 this.set({
  name: n,
  expires: date
 });
 },
 /*查找*/
 get: function(n) {
 n = encodeURIComponent(n);
 var cooikeTotal = document.cookie;
 var cookies = cooikeTotal.split("; ");
 for(var i = 0, len = cookies.length; i < len; i++) {
  var arr = cookies[i].split("=");
  if(n == arr[0]) {
  return decodeURIComponent(arr[1]);
  }
 }
 }
}

下面的是server.js代码,主要对购物车中各种操作进行了封装,比如商品个数统计,更新获取本地数据等操作,方便代码管理,请看代码:

/*
 功能:查看本地数据中是否含有指定的对象(商品),根据id
 参数:id:商品的标识
 */
function checkObjByPid(id) {
 var jsonStr = cookieObj.get("datas");
 var jsonObj = JSON.parse(jsonStr);
 var isExist = false;
 for(var i = 0, len = jsonObj.length; i < len; i++) {
 if(jsonObj[i].pid == id) {
  isExist = true;
  break;
 }
 }
 return isExist; //return false;
}

/*
 功能:更新本地数据
 参数:arr 数组对象
 返回一个值:最新的本地转换后的数组对象
 * */
function updateData(arr) {
 var jsonStr = JSON.stringify(arr);
 cookieObj.set({
 name: "datas",
 value: jsonStr
 });
 jsonStr = cookieObj.get("datas");
 return JSON.parse(jsonStr);
}

/*
 获取商品的总数量
 返回:数字
 */
function getTotalCount() {
 /*循环遍历数组,获取每一个对象中的pCount值相加总和*/
 var totalCount = 0; //默认为0
 var jsonStr = cookieObj.get("datas");
 var listObj = JSON.parse(jsonStr);
 for(var i = 0, len = listObj.length; i < len; i++) {
 totalCount = listObj[i].pCount + totalCount;
 }
 return totalCount;
}

/*
 更新本地数据根据pid
 id:商品的标识
 */
function updateObjById(id, num) {
 var jsonStr = cookieObj.get("datas");
 var listObj = JSON.parse(jsonStr);
 for(var i = 0, len = listObj.length; i < len; i++) {
 if(listObj[i].pid == id) {
  listObj[i].pCount = listObj[i].pCount + num;
  break;
 }
 }
 return updateData(listObj)
}

/*
 获取本地数据
 返回 数组对象
 * */
function getAllData() {
 var jsonStr = cookieObj.get("datas");
 var listObj = JSON.parse(jsonStr);
 return listObj;
}

function deleteObjByPid(id) {
 var lisObj = getAllData();
 for(var i = 0, len = lisObj.length; i < len; i++) {
 if(lisObj[i].pid == id) {
  lisObj.splice(i, 1);
  break;
 }
 }
 updateData(lisObj);
 return lisObj;
}

因为上述代码中涉及了进入购物车后的一些操作,读者看了之后可能会感动疑惑,不用担心,下面请看点击进入我的购物车之后的分析。

请看效果图: 

Javascript实现购物车功能的详细代码

笔者在主页中点击了三种商品,共点击了七次,在购物车中出现了相应商品以及价格计算。对于途中的各种信息,相信读者一目了然。请看本购物车的html代码:

<!DOCTYPE html>
<html>
 <head>
 <meta charset="UTF-8">
 <title>购物车</title>
 <!--购物车样式表-->
 <link rel="stylesheet" type="text/css" href="../css/cart.css" rel="external nofollow" />
 <!--操作cookie的js文件-->
 <script type="text/javascript" src="../js/cookie.js"></script>
 </head>
 <body>
 <div class="container">
  <h1>购物车</h1>
  <h3><a href="index.html" rel="external nofollow" >返回商品列表页面</a></h3>
  <table id="table" border="1" cellspacing="0" cellpadding="0" class="hide">
  <thead>
   <tr>
   <th>
    <input type="checkbox" id="allCheck" class="ck" />全选
   </th>
   <th>
    图片
   </th>
   <th>
    描述
   </th>
   <th>
    数量
   </th>
   <th>
    单价
   </th>
   <th>
    小计
   </th>
   <th>
    操作
   </th>
   </tr>
  </thead>
  <tbody id="tbody">
   <!--
   <tr>
   <td>
    <input type="checkbox" class="ck" />
   </td>
   <td>
    <img src="../images/p1.jpg" alt="" />
   </td>
   <td>
    酷黑,棒棒棒棒
   </td>
   <td>
    <button class="down">-</button><input type="text" value="1" readonly="readonly" /><button class="up">+</button>
   </td>
   <td>
    ¥<span>111</span>
   </td>
   <td>
    ¥<span>111</span>
   </td>
   <td>
    <button class="del" >删除</button>
   </td>
   </tr>
   -->
  </tbody>
  </table>
  <div class="box" id="box">购物车里没有任何商品</div>
  <h2 id="h2" class="">总价格:¥<span id="totalPrice">0</span></h2>
 </div>
 <script src="../js/server.js" type="text/javascript" charset="utf-8"></script>
 <!--操作购物车页面的cart.js-->
 <script src="../js/cart.js"></script>
 </body>
</html>

在对购物车进行相关的表现设计之后,既要进行javascript行为设计,请看与本页相关的cart.js代码:

/*
 思路:
 第一步:当页面加载完后,根据本地的数据,动态生成表格(购物车列表)
  获取所要操作的节点对象
  判断购物车中是否有数据?
  有:
   显示出购物列表
  没有:
   提示购物车为空
 第二步:当购物车列表动态生成后,获取tbody里所有 的checkeBox标签节点对象,看那个被选中就获取对应行小计进行总价格运算。
 第三步:
  为每一个checkbox添加一个onchange事件,根据操作更改总价格
 第四步:全选
 第五步:
  为加减按钮添加一个鼠标点击事件
  更改该商品的数量
 第六步:删除
  获取所有的删除按钮
  为删除按钮添加一个鼠标点击事件
  删除当前行,并更新本地数据
 */

var listObj = getAllData();
var table = document.getElementById("table")
var box = document.getElementById("box")
var tbody = document.getElementById("tbody");
var totalPrice = document.getElementById("totalPrice");
var allCheck = document.getElementById("allCheck");

if(listObj.length == 0) { //购物车为空
 box.className = "box";
 table.className = "hide";
} else {
 box.className = "box hide";
 table.className = "";
 for(var i = 0, len = listObj.length; i < len; i++) {
 var tr = document.createElement("tr");
 tr.setAttribute("pid", listObj[i].pid);
  //{"pid":值,"pImg":值,"pName":值,"pDesc":值,"price":值,"pCount":1},
 tr.innerHTML = '<td>' +
  '<input type="checkbox" class="ck" />' +
  '</td>' +
  '<td>' +
  '<img src="' + listObj[i].pImg + '" alt="" />' +
  '</td>' +
  '<td>' +
  listObj[i].pDesc +
  '</td>' +
  '<td>' +
  '<button class="down">-</button><input type="text" value="' + listObj[i].pCount + '" readonly="readonly" /><button class="up">+</button>' +
  '</td>' +
  '<td>' +
  '¥<span>' + listObj[i].price + '</span>' +
  '</td>' +
  '<td>' +
  '¥<span>' + listObj[i].price * listObj[i].pCount + '</span>' +
  '</td>' +
  '<td>' +
  '<button class="del" >删除</button>' +
  '</td>';
 tbody.appendChild(tr);
 }
}

/*
 功能:计算总价格
 */
var cks = document.querySelectorAll("tbody .ck");
function getTotalPrice() {
 cks = document.querySelectorAll("tbody .ck");
 var sum = 0;
 for(var i = 0, len = cks.length; i < len; i++) {
 if(cks[i].checked) { //如果当前被选中
  var tr = cks[i].parentNode.parentNode;
  var temp = tr.children[5].firstElementChild.innerHTML;
  sum = Number(temp) + sum;
 }
 }
 return sum;
}
/*循环遍历为每一个checkbox添加一个onchange事件*/
for(var i = 0, len = cks.length; i < len; i++) {
 cks[i].onchange = function() {
 checkAllChecked();
 totalPrice.innerHTML = getTotalPrice();
 }
}

/*全选实现*/
allCheck.onchange = function() {
 if(this.checked) {
 for(var i = 0, len = cks.length; i < len; i++) {
  cks[i].checked = true;
 }
 } else {
 for(var i = 0, len = cks.length; i < len; i++) {
  cks[i].checked = false;
 }
 }
 totalPrice.innerHTML = getTotalPrice();
}

var downs = document.querySelectorAll(".down"); //一组减的按钮
var ups = document.querySelectorAll(".up"); //一组加的按钮
var dels = document.querySelectorAll(".del"); //一组删除按钮
for(var i = 0, len = downs.length; i < len; i++) {
 downs[i].onclick = function() {
 var txtObj = this.nextElementSibling;//下一个兄弟节点
 var tr = this.parentNode.parentNode;
 var pid = tr.getAttribute("pid");
 txtObj.value = txtObj.value - 1;
 if(txtObj.value < 1) {
  txtObj.value = 1;
  updateObjById(pid, 0)
 } else {
  updateObjById(pid, -1)
 }
 tr.children[0].firstElementChild.checked = true;
 checkAllChecked();
 var price = tr.children[4].firstElementChild.innerHTML;
 tr.children[5].firstElementChild.innerHTML = price * txtObj.value;
 totalPrice.innerHTML = getTotalPrice();

 }

 ups[i].onclick = function() {
 var txtObj = this.previousElementSibling;//上一个兄弟节点
 var tr = this.parentNode.parentNode;
 var pid = tr.getAttribute("pid");
 txtObj.value = Number(txtObj.value) + 1;
 updateObjById(pid, 1)
 tr.children[0].firstElementChild.checked = true;
 checkAllChecked()
 var price = tr.children[4].firstElementChild.innerHTML;
 tr.children[5].firstElementChild.innerHTML = price * txtObj.value;
 totalPrice.innerHTML = getTotalPrice();
 }

 dels[i].onclick = function() {
 var tr = this.parentNode.parentNode;
 var pid = tr.getAttribute("pid")
 if(confirm("确定删除?")) {
  //remove() 自杀
  tr.remove();
  listObj = deleteObjByPid(pid);
 }
 if(listObj.length == 0) { //购物车为空
  box.className = "box";
  table.className = "hide";
 } else {
  box.className = "box hide";
  table.className = "";
 }
 totalPrice.innerHTML = getTotalPrice();
 }
}

/*检测是否要全选*/
function checkAllChecked() {
 var isSelected = true; //全选是否会选中
 for(var j = 0, len = cks.length; j < len; j++) {
 if(cks[j].checked == false) {
  isSelected = false;
  break;
 }
 }
 allCheck.checked = isSelected;
}

上述代码完成了购物车中的相关操作,比如价格计算,商品数量更换,商品删除等操作。

到这里我们已经完成了购物车的大部分功能,我们对html,css, BOM,DOM,json,cookie等进行了综合应用,相信读者理解之后一定会对自己的javascript学习更进一步,本示例中涉及的大部分代码都在本页中贴出,部分代码资源未向读者展示,读者可以点击下面的资源链接,下载本示例的全部代码及图片资料。本示例采用HBuilder编译器编译运行,涉及cookie操作,请读者自行安装服务器或者添加到HBuilder中运行查看。

资源链接:购物车全部资源下载

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
js trim函数 去空格函数与正则集锦
Nov 20 Javascript
url地址自动加#号问题说明
Aug 21 Javascript
基于jQuery的一个扩展form序列化到json对象
Dec 09 Javascript
JQuery实现用户名无刷新验证的小例子
Mar 22 Javascript
JavaScript立即执行函数的三种不同写法
Sep 05 Javascript
jQuery Ajax调用WCF服务详细教程
Mar 31 Javascript
JavaScript声明变量名的语法规则
Jul 10 Javascript
JS与jQuery遍历Table所有单元格内容的方法
Dec 07 Javascript
AngularJS动态生成div的ID源码解析
Aug 29 Javascript
利用node.js写一个爬取知乎妹纸图的小爬虫
May 03 Javascript
jQuery判断网页是否已经滚动到浏览器底部的实现方法
Oct 27 jQuery
layui实现数据表格隐藏列的示例
Oct 25 Javascript
vue-cli 如何打包上线的方法示例
May 08 #Javascript
使用vue-cli打包过程中的步骤以及问题的解决
May 08 #Javascript
详解React-Router中Url参数改变页面不刷新的解决办法
May 08 #Javascript
angularjs实现的购物金额计算工具示例
May 08 #Javascript
Vue微信项目按需授权登录策略实践思路详解
May 07 #Javascript
Vue + better-scroll 实现移动端字母索引导航功能
May 07 #Javascript
node使用promise替代回调函数
May 07 #Javascript
You might like
php动态实现表格跨行跨列实现代码
2012/11/06 PHP
php+mysql大量用户登录解决方案分析
2014/12/29 PHP
php输出全球各个时区列表的方法
2015/03/31 PHP
Jquery跨域获得Json时invalid label错误的解决办法
2011/01/11 Javascript
字符串的replace方法应用浅析
2011/12/06 Javascript
ASP.NET jQuery 实例18 通过使用jQuery validation插件校验DropDownList
2012/02/03 Javascript
浅析jQuery Mobile的初始化事件
2015/12/03 Javascript
JS获取中文拼音首字母并通过拼音首字母快速查找页面内对应中文内容的方法【附demo源码】
2016/08/19 Javascript
easyui combotree加载静态数据问题(选不上)解决方法
2016/12/26 Javascript
2种简单的js倒计时方式
2017/10/20 Javascript
详解PHP后期静态绑定分析与应用
2018/03/21 Javascript
vue组件详解之使用slot分发内容
2018/04/09 Javascript
jQuery实现文件编码成base64并通过AJAX上传的方法
2018/04/12 jQuery
[02:32]“虐狗”镜头慎点 2016国际邀请赛中国区预选赛现场玩家采访
2016/06/28 DOTA
在Python程序中操作MySQL的基本方法
2015/07/29 Python
使用Python的urllib和urllib2模块制作爬虫的实例教程
2016/01/20 Python
Python中asyncore异步模块的用法及实现httpclient的实例
2016/06/28 Python
CentOS 6.5下安装Python 3.5.2(与Python2并存)
2017/06/05 Python
简单谈谈python中的语句和语法
2017/08/10 Python
Python Web编程之WSGI协议简介
2018/07/18 Python
Python替换月份为英文缩写的实现方法
2019/07/15 Python
Python爬虫实现“盗取”微信好友信息的方法分析
2019/09/16 Python
pytorch实现建立自己的数据集(以mnist为例)
2020/01/18 Python
pytorch  网络参数 weight bias 初始化详解
2020/06/24 Python
Python设计密码强度校验程序
2020/07/30 Python
作为网站管理者应当如何防范XSS
2014/08/16 面试题
活动邀请函范文
2014/01/19 职场文书
平面设计专业求职信
2014/08/09 职场文书
我的中国梦演讲稿小学篇
2014/08/19 职场文书
关于读书的演讲稿500字
2014/08/27 职场文书
解除劳动合同协议书
2014/09/17 职场文书
乡镇团代会开幕词
2016/03/04 职场文书
祝福语集锦:朋友新店开业祝福语
2019/12/10 职场文书
python 使用Tensorflow训练BP神经网络实现鸢尾花分类
2021/05/12 Python
浅析python中特殊文件和特殊函数
2022/02/24 Python
Python中np.random.randint()参数详解及用法实例
2022/09/23 Python