1. 程式人生 > >javascript購物車實現詳細程式碼講解

javascript購物車實現詳細程式碼講解

我們肯定都很熟悉商品購物車這一功能,每當我們在某寶某東上購買商品的時候,看中了哪件商品,就會加入購物車中,最後結算。購物車這一功能,方便消費者對商品進行管理,可以新增商品,刪除商品,選中購物車中的某一項或幾項商品,最後商品總價也會隨著消費者的操作隨著變化。
現在,筆者對購物車進行了簡單實現,能夠實現真實購物車當中的大部分功能。在本示例當中,用到了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中執行檢視。
資源連結:購物車全部資源下載