随着互联网的发展,尤其是移动互联网的快速崛起,软件技术的开发已经越来越细分,不再是当年一种技术或者一种语言走天下的年代,元芒数字的攻城狮们不断的努力着,下文是就购物车这个电商环节中一定会存在的案子,让我们来看攻城狮忠远的表演。”
我们肯定都很熟悉商品购物车这一功能,每当我们在某宝某东上购买商品的时候,看中了哪件商品,就会加入购物车中,最后结算。购物车这一功能,方便消费者对商品进行管理,可以添加商品,删除商品,选中购物车中的某一项或几项商品,最后商品总价也会随着消费者的操作随着变化,尤其是为了配合线上花样翻新的营销活动,购物车的功能必须强大而迅速。
现在,对购物车进行了简单实现,能够实现真实购物车当中的大部分功能。在本示例当中,用到了javascript中BOM操作,DOM操作,表格操作,cookie,json等知识点,同时,采用三层架构方式对购物车进行设计,对javascript的综合应用较强。
主页效果图
图1
现在读者已经对主页的效果图进行了了解,我在这里附上主页的html代码,供读者参考,建议读者根据自己的思路写代码。请看html代码:
<!DOCTYPE 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;
}
因为上述代码中涉及了进入购物车后的一些操作,读者看了之后可能会感到疑惑,不用担心,下面请看点击进入我的购物车之后的分析。请看效果图:
图2
笔者在主页中点击了三种商品,共点击了七次,在购物车中出现了相应商品以及价格计算。对于途中的各种信息,相信读者一目了然。请看本购物车的html代码:
<!DOCTYPE html>
全选
图片
描述
数量
单价
小计
操作
总价格:¥0
在对购物车进行相关的表现设计之后,既要进行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 = '
' +'' +
'
' +'
' +'' +
'
' +'
' +listObj[i].pDesc +
'
' +'
' +'' +
'
' +'
' +'¥' + listObj[i].price + '' +
'
' +'
' +'¥' + listObj[i].price * listObj[i].pCount + '' +
'
' +'
' +'' +
'
';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();
}
}
//代码效果参考:http://www.zidongmutanji.com/zsjx/562931.html
/全选实现/
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等进行了综合应用。