這算一次復(fù)盤吧,接到的一個需求:前后分離终娃,前端走完一個簡單購物流程味廊,然后最后將數(shù)據(jù)提交給后臺。
第一次寫的時候?qū)懙猛靵y的棠耕,埋了不少坑余佛,同事看不下去了,幫忙填了一次坑窍荧。o(╥﹏╥)o(真的不想坑人)
后面自己整理了下思路辉巡,私下自己在重新寫了一遍,這里記錄一下.
這次主要收獲:
1. 前后分離思想
2. cookie的應(yīng)用
3. 改掉混亂的面條式代碼,提升復(fù)用率蕊退,模塊化編程
需求分析
- 首先,一共四個頁面:
首頁——>產(chǎn)品列表頁——>購物車頁面——>結(jié)算頁面 - 需要實現(xiàn)的功能點:
- 在首頁和產(chǎn)品列表頁點擊某產(chǎn)品可以加入購物車
- 如果該產(chǎn)品已經(jīng)在購物車內(nèi)則不能重復(fù)加入
- 每個頁面頭部購物車數(shù)量更新
- 在購物車頁面時歷遍出在購物車中的產(chǎn)品
- 計算以及顯示 產(chǎn)品總價郊楣、運費、以及訂單總價(運費+總價)
- 進入結(jié)算頁面歷遍出需要結(jié)算的產(chǎn)品和單價瓤荔,以及更新產(chǎn)品總價净蚤,和訂單總價(加運費);
- 加急運費,如果勾選加急運費則加上運費输硝,如果不勾選則恢復(fù)今瀑。
- 如果所購買的產(chǎn)品中有Monthy產(chǎn)品,則顯示相應(yīng)協(xié)議点把,如果沒有則不顯示橘荠。
- 在結(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)幾個點:
- 創(chuàng)建一個對象作為產(chǎn)品衣厘,對象key值有[產(chǎn)品ID]如蚜、[產(chǎn)品名字]、[產(chǎn)品價格]影暴、[是否是monthy產(chǎn)品]错邦。
- 判斷是否已經(jīng)存有cookie,如果沒有型宙,則建立一個新數(shù)組撬呢,并push入新加的產(chǎn)品,并存儲入cookie;
- 如果已有cookie妆兑,則取出cookie賦值給一個變量魂拦,歷遍該變量毛仪。這里需要實現(xiàn)兩個功能點:
- 判斷這個產(chǎn)品是否加入過購物車
- 在歷遍的同時,加出所有產(chǎn)品的總價芯勘。
- 如果購物車內(nèi)沒有此產(chǎn)品箱靴,則可以將改產(chǎn)品push入數(shù)組,并更新總價荷愕,然后存入cookie衡怀。
- 調(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)品:
- 點擊刪除按鈕時癣蟋,傳入該產(chǎn)品id以及this透硝。
- 取出cookie以及總價,賦值給個數(shù)組疯搅,并歷遍該數(shù)組濒生,這里需要實現(xiàn)2點:
- 如果產(chǎn)品id與傳入的id相同,則從數(shù)組中刪除該元素幔欧。
- 總價減去改產(chǎn)品價格罪治,更新cookie。
- 刪除頁面元素礁蔗,更新頁面價格觉义,更新購物車個數(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ù)的存取上奄喂。
動手寫代碼前需要理清思路铐殃,思路清晰了,一個小點一個小點的寫下來就會順利很多跨新,并且會避免遺漏富腊。