javascript购物车实现详细代码讲解

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zhongguohaoshaonian/article/details/52684766

我们肯定都很熟悉商品购物车这一功能,每当我们在某宝某东上购买商品的时候,看中了哪件商品,就会加入购物车中,最后结算。购物车这一功能,方便消费者对商品进行管理,可以添加商品,删除商品,选中购物车中的某一项或几项商品,最后商品总价也会随着消费者的操作随着变化。
现在,笔者对购物车进行了简单实现,能够实现真实购物车当中的大部分功能。在本示例当中,用到了javascript中BOM操作,DOM操作,表格操作,cookie,json等知识点,同时,采用三层架构方式对购物车进行设计,对javascript的综合应用较强,对javascript初学者进阶有一定的益处。
请看主页效果图:
这里写图片描述
现在读者已经对主页的效果图进行了了解,我在这里附上主页的html代码,供读者参考,建议读者根据自己的思路写代码。请看html代码:

<!DOCTYPE html>
<html>

    <head>
        <meta charset="utf-8" />
        <title>商品列表页面</title>
        <!--商品列表样式表-->
        <link rel="stylesheet" type="text/css" href="../css/index.css" />
        <!--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">我的购物车</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;
}

因为上述代码中涉及了进入购物车后的一些操作,读者看了之后可能会感动疑惑,不用担心,下面请看点击进入我的购物车之后的分析。
请看效果图:
这里写图片描述
笔者在主页中点击了三种商品,共点击了七次,在购物车中出现了相应商品以及价格计算。对于途中的各种信息,相信读者一目了然。请看本购物车的html代码:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>购物车</title>
        <!--购物车样式表-->
        <link rel="stylesheet" type="text/css" href="../css/cart.css" />
        <!--操作cookie的js文件-->
        <script type="text/javascript" src="../js/cookie.js"></script>
    </head>
    <body>
        <div class="container">
            <h1>购物车</h1>
            <h3><a href="index.html">返回商品列表页面</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中运行查看。
资源链接:购物车全部资源下载

阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页