前后分離:實現(xiàn)一個簡易的購物流程

這算一次復(fù)盤吧,接到的一個需求:前后分離终娃,前端走完一個簡單購物流程味廊,然后最后將數(shù)據(jù)提交給后臺。
第一次寫的時候?qū)懙猛靵y的棠耕,埋了不少坑余佛,同事看不下去了,幫忙填了一次坑窍荧。o(╥﹏╥)o(真的不想坑人)
后面自己整理了下思路辉巡,私下自己在重新寫了一遍,這里記錄一下.
這次主要收獲:
1. 前后分離思想
2. cookie的應(yīng)用
3. 改掉混亂的面條式代碼,提升復(fù)用率蕊退,模塊化編程


需求分析
  • 首先,一共四個頁面:
    首頁——>產(chǎn)品列表頁——>購物車頁面——>結(jié)算頁面
  • 需要實現(xiàn)的功能點:
    1. 在首頁和產(chǎn)品列表頁點擊某產(chǎn)品可以加入購物車
    2. 如果該產(chǎn)品已經(jīng)在購物車內(nèi)則不能重復(fù)加入
    3. 每個頁面頭部購物車數(shù)量更新
    4. 在購物車頁面時歷遍出在購物車中的產(chǎn)品
    5. 計算以及顯示 產(chǎn)品總價郊楣、運費、以及訂單總價(運費+總價)
    6. 進入結(jié)算頁面歷遍出需要結(jié)算的產(chǎn)品和單價瓤荔,以及更新產(chǎn)品總價净蚤,和訂單總價(加運費);
    7. 加急運費,如果勾選加急運費則加上運費输硝,如果不勾選則恢復(fù)今瀑。
    8. 如果所購買的產(chǎn)品中有Monthy產(chǎn)品,則顯示相應(yīng)協(xié)議点把,如果沒有則不顯示橘荠。
    9. 在結(jié)算頁面提交時需要校驗信息。

具體實現(xiàn)

1.建立一個JSON愉粤,存放產(chǎn)品的數(shù)據(jù)信息,如:

var productInfo = {
    "product-des_1": "A bottle of drink",    //產(chǎn)品名字
    "product-des_2": "2 bottles of drinks",
    "product-des_3": "3 bottles of drinks",
    "product-des_4": "4 bottles of drinks",
    "product-des_5": "5 bottles of drinks",
    "product-des_6": "Buy one bottle a month"
    "product-price_1": 9.99,         //對應(yīng)的產(chǎn)品價格
    "product-price_2": 19.99,
    "product-price_3": 29.99,
    "product-price_4": 39.99,
    "product-price_5": 49.99,
    "shipping-price"  : 8.00,       //加急運費
    "shipping-fee": 0               //運費
};

2.加入購物車

當(dāng)某產(chǎn)品點擊加入購物車按鈕時砾医,傳入對應(yīng)產(chǎn)品的id,如:

<a class="btn" onclick="addCart(3);">ADD TO CART</a>

在接收這個id后,需要實現(xiàn)幾個點:

  1. 創(chuàng)建一個對象作為產(chǎn)品衣厘,對象key值有[產(chǎn)品ID]如蚜、[產(chǎn)品名字]、[產(chǎn)品價格]影暴、[是否是monthy產(chǎn)品]错邦。
  2. 判斷是否已經(jīng)存有cookie,如果沒有型宙,則建立一個新數(shù)組撬呢,并push入新加的產(chǎn)品,并存儲入cookie;
  3. 如果已有cookie妆兑,則取出cookie賦值給一個變量魂拦,歷遍該變量毛仪。這里需要實現(xiàn)兩個功能點:
    1. 判斷這個產(chǎn)品是否加入過購物車
    2. 在歷遍的同時,加出所有產(chǎn)品的總價芯勘。
  4. 如果購物車內(nèi)沒有此產(chǎn)品箱靴,則可以將改產(chǎn)品push入數(shù)組,并更新總價荷愕,然后存入cookie衡怀。
  5. 調(diào)用修改購物車個數(shù)。
function addCart(productId){
    var productDes = "product-des_" + productId;
    var productPri = "product-price_" + productId;
    var proName = productInfo[productDes];
    var pPrice = productInfo[productPri];
    
    var products = {};
    products.id = productId;
    products.name = proName;
    products.price = pPrice;
    //判斷是否是Monthy產(chǎn)品
    if(proName.indexOf('month') != -1){
        products.auto = 1;
    }
    
    if(typeof $.cookie('productList') == 'undefined'){
        var proList = [];
        proList.push(products);
        
        $.cookie('productList', JSON.stringify(proList));
        $.cookie('proTotal', pPrice.toFixed(2));
    }else{
        var proList = JSON.parse($.cookie('productList'));
        var isAdd = true;
        var pTotal = 0;
        
        for(let i=0; i<proList.length; i++){
            let p = proList[i];
            if(p.id == productId){
                isAdd = false;
            }
            
            pTotal = pTotal + p.price;
        }
        
        if(isAdd){
            proList.push(products);
            pTotal = pTotal + products.price;
            
            $.cookie('productList', JSON.stringify(proList));
            $.cookie('proTotal', pTotal.toFixed(2));
        }
    }
    
    //更新購物車數(shù)量
    innerCartCount();
    
}

3.修改購物車個數(shù)
html頁面上:

<span>Cart(<b id="cartNum">0</b>)</span>

首先需要判斷頁面上是否有這個元素(以防在其他頁面調(diào)用的時候報錯)安疗,并且需要判斷是否存儲了產(chǎn)品cookie抛杨。
取出cookie賦值給變量,讀取該變量的個數(shù)荐类,并更改頁面上的數(shù)量怖现。

function innerCartCount(){
    var cartNum = document.getElementById('cartNum');
    if(cartNum != null && cartNum != ''){
        if(typeof $.cookie('productList') != 'undefined'){
            var proList = JSON.parse($.cookie('productList'));
            var count = proList.length;
            
            cartNum.innerHTML = count;
        }
    }
}

在這里需要注意一定,除了加入購物車時調(diào)用外掉冶,也需要在外面調(diào)用這個函數(shù)真竖,解決頁面一刷新,數(shù)量就清零的尷尬問題厌小。

4.購物車頁面

歷遍出所有產(chǎn)品(產(chǎn)品名字恢共、價格、以及刪除按鈕)

function innerCartBodyHtml(){
    var cartBody = document.getElementById('cartBody');
    if(cartBody != null && cartBody != ''){
        if(typeof $.cookie('productList') != 'undefined'){
            var proList = JSON.parse($.cookie('productList'));
            var html = '';
            
            for(let i=0; i<proList.length; i++){
                let p = proList[i];
                html = html + `
                    <tr>
                        <td>${p.name}</td>
                        <td>${p.price}</td>
                        <td class='remove'>
                            <a class="btn btn-default" onclick="removeCart(${p.id},this)">remove</a>
                        </td>
                    </tr>
                `
            }
            
            cartBody.innerHTML = html;
        }
    }
}

更新頁面產(chǎn)品總價璧亚、運費讨韭、以及訂單總價。

function innerPrice(){
    if(typeof $.cookie('proTotal') != 'undefined'){
        var proTotal = Number($.cookie('proTotal'));
        
        //產(chǎn)品總價
        var subTotal = document.getElementById('subTotal');
        if(subTotal != null && subTotal != ''){
            subTotal.innerHTML = '$' + proTotal.toFixed(2);
        }
        
        //運費
        var shipFee = document.getElementById('shipFee');
        if(shipFee != null && shipFee != ''){
            var shipFeePrice = Number(productInfo['shipping-fee']);
            shipFee.innerHTML = shipFeePrice.toFixed(2);
        }
        
        //訂單總價
        var orderTotal = document.getElementById('orderTotal');
        if(orderTotal != null && orderTotal != ''){
            var oTotal = proTotal + shipFeePrice;
            
            $.cookie('orderTotal',oTotal.toFixed(2));
            orderTotal.innerHTML = '$' + oTotal.toFixed(2);
        }
        
    }
}

刪除購物車產(chǎn)品:

  1. 點擊刪除按鈕時癣蟋,傳入該產(chǎn)品id以及this透硝。
  2. 取出cookie以及總價,賦值給個數(shù)組疯搅,并歷遍該數(shù)組濒生,這里需要實現(xiàn)2點:
    1. 如果產(chǎn)品id與傳入的id相同,則從數(shù)組中刪除該元素幔欧。
    2. 總價減去改產(chǎn)品價格罪治,更新cookie。
  3. 刪除頁面元素礁蔗,更新頁面價格觉义,更新購物車個數(shù)。
function removeCart(productId, obj){
    if(typeof $.cookie('productList') != 'undefined'){
        var proList = JSON.parse($.cookie('productList'));
        var pTotal = Number($.cookie('proTotal'));
        
        for(let i=0; i<proList.length; i++){
            let p = proList[i];
            if(p.id == productId){
                proList.splice(i,1);
                pTotal = pTotal - p.price;
                
                $.cookie('productList', JSON.stringify(proList));
                $.cookie('proTotal', pTotal.toFixed(2));
            }
        }
        
        //刪除頁面元素
        var cartTr = obj.parentNode.parentNode;
        var cartTbody = cartTr.parentNode;
        cartTbody.removeChild(cartTr);
        
        //更新價格
        innerPrice();
        
        //更新購物車數(shù)量
        innerCartCount();
    }
}

5.結(jié)算頁面

結(jié)算頁面需要歷遍出需要結(jié)算的產(chǎn)品浴井,和購物車的歷遍差不多晒骇,但是這里不能刪除,只要產(chǎn)品名和價格。

function innerCheckoutProductListHtml(){
    var checkoutProList = document.getElementById('checkoutProductList');
    if(checkoutProList != null && checkoutProList != ''){
        if(typeof $.cookie('productList') != 'undefined'){
            var proList = JSON.parse($.cookie('productList'));
            var html = '';
            for(let i=0; i<proList.length; i++){
                let p = proList[i];
                html = html + `
                    <li>
                        <span class="pull-left">${p.name}</span>
                        <span class="pull-right">${p.price}</span>
                    </li>
                `
            }
            
            checkoutProList.innerHTML = html;
        }
    }
}

更新頁面運費:
這里主要是將頁面顯示運費處寫活洪囤,至于產(chǎn)品總價和訂單已經(jīng)寫過徒坡,結(jié)算頁面只需要加上對應(yīng)id即可,不用重復(fù)寫箍鼓。

function getShippingPrice(){
    var shippingPrice = document.getElementById('shippingPrice');
    if(shippingPrice != null && shippingPrice != ''){
        var shipPrice = Number(productInfo['shipping-price']);
        shippingPrice.innerHTML = '$' + shipPrice;
    }
}

是否勾選加急運費

function fastshippingClick(){
    var fastShipping = document.getElementById('fastshipping');
    var orderTotal = document.getElementById('orderTotal');
    var ProtectPack = document.getElementById('ProtectPack');
    
    if(orderTotal != null && orderTotal != ''){
        if(typeof $.cookie('orderTotal') != 'undefined'){
            var oTotal = Number($.cookie('orderTotal'));
            
            if(fastShipping.checked){
                oTotal = oTotal + Number(productInfo['shipping-price']);
                orderTotal.innerHTML = '$' + oTotal.toFixed(2);
                ProtectPack.value = 1;
            }else{
                orderTotal.innerHTML = '$' + oTotal.toFixed(2);
                ProtectPack.value = 0;
            }
        }
    }
}

是否存在Monthy產(chǎn)品崭参,如果存在呵曹,顯示出對應(yīng)的條款說明款咖,不存在則隱藏

function checkSubs(){
    var chkSubs = document.getElementById('chk_subs');
    var proInfo = document.getElementById('proinfo');
    if(chkSubs != null && chkSubs != '' && proInfo != null && proInfo != ''){
        if(typeof $.cookie('productList') != 'undefined'){
            var html = '';
            var isShow = false;
            var proList = JSON.parse($.cookie('productList'));
            
            for(let i=0; i<proList.length; i++){
                let p = proList[i];
                if(p.auto == 1){
                    isShow = true;
                    html = html + `<li><b>${p.price} for Level 8 ${p.name}</b></li>`;
                }
            }
            
            proInfo.innerHTML = html;
            
            //如果又monthy產(chǎn)品顯示條款
            if(isShow){
                chkSubs.style.display = 'block';    
            }
            
        }
    }
}

總結(jié):

一個簡單的購物流程,其實主要的點就是在購物車添加刪除以及數(shù)據(jù)的存取上奄喂。
動手寫代碼前需要理清思路铐殃,思路清晰了,一個小點一個小點的寫下來就會順利很多跨新,并且會避免遺漏富腊。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市域帐,隨后出現(xiàn)的幾起案子赘被,更是在濱河造成了極大的恐慌,老刑警劉巖肖揣,帶你破解...
    沈念sama閱讀 211,743評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件民假,死亡現(xiàn)場離奇詭異,居然都是意外死亡龙优,警方通過查閱死者的電腦和手機羊异,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,296評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來彤断,“玉大人野舶,你說我怎么就攤上這事≡籽茫” “怎么了平道?”我有些...
    開封第一講書人閱讀 157,285評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長供炼。 經(jīng)常有香客問我一屋,道長,這世上最難降的妖魔是什么劲蜻? 我笑而不...
    開封第一講書人閱讀 56,485評論 1 283
  • 正文 為了忘掉前任陆淀,我火速辦了婚禮,結(jié)果婚禮上先嬉,老公的妹妹穿的比我還像新娘轧苫。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 65,581評論 6 386
  • 文/花漫 我一把揭開白布含懊。 她就那樣靜靜地躺著身冬,像睡著了一般。 火紅的嫁衣襯著肌膚如雪岔乔。 梳的紋絲不亂的頭發(fā)上酥筝,一...
    開封第一講書人閱讀 49,821評論 1 290
  • 那天,我揣著相機與錄音雏门,去河邊找鬼嘿歌。 笑死,一個胖子當(dāng)著我的面吹牛茁影,可吹牛的內(nèi)容都是我干的宙帝。 我是一名探鬼主播,決...
    沈念sama閱讀 38,960評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼募闲,長吁一口氣:“原來是場噩夢啊……” “哼步脓!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起浩螺,我...
    開封第一講書人閱讀 37,719評論 0 266
  • 序言:老撾萬榮一對情侶失蹤靴患,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后要出,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體鸳君,經(jīng)...
    沈念sama閱讀 44,186評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,516評論 2 327
  • 正文 我和宋清朗相戀三年厨幻,在試婚紗的時候發(fā)現(xiàn)自己被綠了相嵌。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,650評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡况脆,死狀恐怖饭宾,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情格了,我是刑警寧澤看铆,帶...
    沈念sama閱讀 34,329評論 4 330
  • 正文 年R本政府宣布,位于F島的核電站盛末,受9級特大地震影響弹惦,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜悄但,卻給世界環(huán)境...
    茶點故事閱讀 39,936評論 3 313
  • 文/蒙蒙 一棠隐、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧檐嚣,春花似錦助泽、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,757評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽隐解。三九已至,卻和暖如春诫睬,著一層夾襖步出監(jiān)牢的瞬間煞茫,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,991評論 1 266
  • 我被黑心中介騙來泰國打工摄凡, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留续徽,地道東北人。 一個月前我還...
    沈念sama閱讀 46,370評論 2 360
  • 正文 我出身青樓架谎,卻偏偏與公主長得像炸宵,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子谷扣,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,527評論 2 349

推薦閱讀更多精彩內(nèi)容