原生js實(shí)現(xiàn)計(jì)算購物車總金額的示例
隨著vue、react、angular等MVVM框架的興起。讓之前需要對dom進(jìn)行復(fù)雜操作才能實(shí)現(xiàn)的需求變得如此簡單。確實(shí),作為數(shù)據(jù)驅(qū)動(dòng)dom的框架,讓我們在項(xiàng)目中變得愈加游刃有余。但是當(dāng)我們享受他給我們帶來的便利時(shí),適當(dāng)?shù)膶υ牧私庖材軐ξ覀兗夹g(shù)的提升大有裨益。而且通過適當(dāng)?shù)木帉慾s原生代碼實(shí)現(xiàn)相應(yīng)功能,也能更讓我們喜歡上MVVM框架。廢話少說:先通過效果圖(左邊為編輯購物車,右邊為購物車列表)了解下需求:
- 當(dāng)點(diǎn)擊商品復(fù)選框,當(dāng)前商品的總價(jià)會(huì)被計(jì)算到合計(jì)費(fèi)用中去
- 當(dāng)點(diǎn)擊商品數(shù)量增減且此時(shí)商品對應(yīng)的復(fù)選框處于選中狀態(tài)時(shí),合計(jì)費(fèi)用會(huì)發(fā)生改變
- 點(diǎn)擊全選時(shí),所有商品的復(fù)選框都被選中且合計(jì)費(fèi)用為所有商品總價(jià)
- 點(diǎn)擊編輯,此處文字變?yōu)?ldquo;完成”,右下角的去結(jié)算按鈕變?yōu)榧t色刪除按鈕
- 在編輯購物車情況下,當(dāng)我們勾選對應(yīng)商品的復(fù)選框然后點(diǎn)擊刪除,對應(yīng)的商品會(huì)被清除,且合計(jì)費(fèi)用為重置為0,“完成”變?yōu)?ldquo;編輯”,刪除按鈕變?yōu)槿ソY(jié)算。


需求痛點(diǎn):這個(gè)需求的難點(diǎn)在于如何去將每個(gè)商品的總價(jià)匯集起來然后隨著復(fù)選框的狀態(tài)累加到合計(jì)費(fèi)用中去。我們先看下商品的html結(jié)構(gòu):
<div class="cartMain1" data-id=${goods_id}>
<input type="checkbox" class="checkbox" />
<input type="hidden" class="hiddenVal">
<div class="cartMsg">
<img src="${goods_image}" alt="" />
<div class="cartDetail2">
<h3>${goods_name}</h3>
<div class="cartDCont">
<p class="commonMoney">¥<span class="singlePrice">${goods_price_max}</span></p>
<div class="count">
<button class="decrease">-</button>
<input type="text" class="goodsSum" value=${goods_num} />
<button class="increase">+</button>
</div>
</div>
</div>
</div>
</div>我是這樣解決上述難點(diǎn)的:我在每個(gè)商品的復(fù)選框下面增加一個(gè)隱藏域,它的值為當(dāng)前商品的總價(jià),當(dāng)商品的數(shù)量發(fā)生改變時(shí),我會(huì)將商品最終價(jià)格賦值各他的value值,然后我們在通過遍歷所有復(fù)選框的選中狀態(tài)拿到對應(yīng)的隱藏域value值就得出我們想要的總價(jià)了。具體js代碼如下:
1、遍歷隱藏input的值獲取金額
function getHiddenMoney() {
let str = 0;
Array.from(checkboxEl).forEach((item) => {
if (item.checked == true) {
str += +item.nextElementSibling.value;
}
});
document.querySelector(".totalPrice").innerHTML = str.toFixed(2);
}2、點(diǎn)擊子復(fù)選框?qū)⒔痤~賦值給隱藏input
function toHiddenMoney(el) {
? const parent = el.parentNode;
? //獲取單價(jià)元素
? const singlePrice = +parent.querySelector(".singlePrice").innerHTML;
? //獲取商品數(shù)量
? const goodsSum = +parent.querySelector(".goodsSum").value;
? //商品總價(jià)為
? let totalPriceVal = (singlePrice * goodsSum).toFixed(2);
? //賦值給hidden input框
? el.nextElementSibling.value = totalPriceVal;
? getTotalMoney();
}3、點(diǎn)擊子復(fù)選框給父復(fù)選框添加狀態(tài)
for (let i = 0; i < box.length; i++) {
box[i].addEventListener("click", function () {
checkbox.checked = Array.from(box).every((item) => item.checked);
toHiddenMoney(box[i]);
});
} 4、點(diǎn)擊全選復(fù)選框=>所有復(fù)選框都被選中
const checkbox = document.querySelector("#checkbox");
const box = document.querySelectorAll(".checkbox");
checkbox.addEventListener("click", function () {
for (let i = 0; i < box.length; i++) {
box[i].checked = checkbox.checked;
toHiddenMoney(box[i]);
}
});
5、點(diǎn)擊商品數(shù)量增減時(shí)
let goodCount = document.querySelectorAll(".count");
goodCount.forEach((item) => {
item.addEventListener("click", function (e) {
let target = e.target;
if (target.className == "decrease") {
const inp = target.nextElementSibling;
const hidden =
target.parentNode.parentNode.parentNode.parentNode
.previousElementSibling;
const checkBox =
target.parentNode.parentNode.parentNode.parentNode
.previousElementSibling.previousElementSibling;
const singleVal =
+target.parentNode.previousElementSibling.querySelector(
".singlePrice"
).innerHTML;
if (inp.value == 1) {
return alert("不能再減了~");
} else {
inp.value--;
hidden.value = singleVal * inp.value;
toHiddenMoney(checkBox);
}
}
if (target.className == "increase") {
const inp = target.previousElementSibling;
const hidden =
target.parentNode.parentNode.parentNode.parentNode
.previousElementSibling;
const checkBox =
target.parentNode.parentNode.parentNode.parentNode
.previousElementSibling.previousElementSibling;
const singleVal =
+target.parentNode.previousElementSibling.querySelector(
".singlePrice"
).innerHTML;
inp.value++;
hidden.value = singleVal * inp.value;
toHiddenMoney(checkBox);
}
});
});
const checkboxEl = document.querySelectorAll(".checkbox");6、點(diǎn)擊編輯
const edit = document.querySelector(".edit");
let flag = true;
const editHtml = edit.innerHTML;
const account = document.querySelector(".account");
const cancel = document.querySelector(".cancel");
let newCheckbox = [];
edit.addEventListener("click", function () {
let editHtml2 = `<span style="color: red; font-size: 3.7333vw">完成</span>`;
console.log(flag);
if (flag) {
this.innerHTML = editHtml2;
account.style.display = "none";
cancel.style.display = "block";
} else {
this.innerHTML = editHtml;
account.style.display = "block";
cancel.style.display = "none";
}
flag = !flag;
});7、點(diǎn)擊刪除按鈕
let goodsIdArr = [];
cancel.addEventListener("click", function () {
//獲取被選中的復(fù)選框
newCheckbox = [...checkboxEl].filter((item) => item.checked == true);
newCheckbox.forEach((item) => {
item.parentNode.remove();
goodsIdArr.push(item.parentNode.dataset.id);
});
edit.innerHTML = editHtml;
account.style.display = "block";
cancel.style.display = "none";
document.querySelector(".totalPrice").innerHTML = +0.0;
});
8、封裝獲取復(fù)選框的狀態(tài)來計(jì)算總費(fèi)用
function getTotalMoney() {
let checkboxNew = document.querySelectorAll(".checkbox");
arr = [];
for (let i = 0; i < checkboxNew.length; i++) {
if (checkboxNew[i].checked == true) {
arr.push(+checkboxNew[i].nextElementSibling.value);
getTotalPrice(arr);
} else {
getTotalPrice(arr);
}
}
}9、計(jì)算總價(jià)
function getTotalPrice(arr) {
document.querySelector(".totalPrice").innerHTML = arr
.reduce((prev, cur) => prev + cur, 0)
.toFixed(2);
}
以上就是我用原生js實(shí)現(xiàn)購物車總金額的代碼。寫的時(shí)候也是備受煎熬。用原生js真的很繁瑣。我的代碼邏輯我覺得還有改進(jìn)的地方,還望各位大神指點(diǎn)指點(diǎn)。歡迎大家點(diǎn)評~
相關(guān)文章
javascript 就地編輯實(shí)現(xiàn)代碼
最近正在看《javascript設(shè)計(jì)模式》,其中有一個(gè)'就地編輯'的示例,用來表現(xiàn)不同的繼承方式,看完之后想自己憑理解寫一個(gè)類似的東西。2010-05-05
使用Three.js制作一個(gè)3D獎(jiǎng)牌頁面
本文將使用React+Three.js技術(shù)棧,制作一個(gè)專屬的3D獎(jiǎng)牌頁面,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起動(dòng)手試一試2022-01-01
JavaScript必知必會(huì)(十) call apply bind的用法說明
這篇文章主要介紹了JavaScript必知必會(huì)(十) call apply bind的用法說明 的相關(guān)資料,非常不錯(cuò)具有參考借鑒價(jià)值,需要的朋友可以參考下2016-06-06
寫了10年的Javascript也未必全了解的連續(xù)賦值運(yùn)算
很喜歡 蔡蔡 的這個(gè)標(biāo)題,實(shí)際蔡蔡已經(jīng)分析過了,這里借用了。或許有點(diǎn)標(biāo)題黨的意思。看完就知了。2011-03-03
45個(gè)JavaScript編程注意事項(xiàng)、技巧大全
這篇文章主要介紹了45個(gè)JavaScript編程注意事項(xiàng)、技巧大全,在這篇文章里,我將分享一些JavaScript的技巧、秘訣和最佳實(shí)踐,除了少數(shù)幾個(gè)外,不管是瀏覽器的JavaScript引擎,還是服務(wù)器端JavaScript解釋器,均適用,需要的朋友可以參考下2015-02-02
javascript計(jì)算當(dāng)月剩余天數(shù)(天數(shù)計(jì)算器)示例代碼
本文介紹了利用Javascript在網(wǎng)頁上計(jì)算當(dāng)前月份的剩余天數(shù)的方法,大家參考使用吧2014-01-01
微信小程序首頁的分類功能和搜索功能的實(shí)現(xiàn)思路及代碼詳解
這篇文章主要介紹了微信小程序首頁的分類功能和搜索功能的實(shí)現(xiàn)思路及代碼詳解,微信宣布了微信小程序開發(fā)者工具新增“云開發(fā)”功能,現(xiàn)在無需服務(wù)器即可實(shí)現(xiàn)小程序的快速迭代,感興趣的朋友跟隨小編一起看看吧2018-09-09
詳解ant-design-pro使用qiankun微服務(wù)
這篇文章主要介紹了ant-design-pro使用qiankun微服務(wù)詳解,其實(shí)微服務(wù)需要有主應(yīng)用和子應(yīng)用,?一個(gè)子應(yīng)用可以配置多個(gè)相關(guān)聯(lián)的主應(yīng)用,配置方法都是一樣的,對ant-design-pro微服務(wù)配置相關(guān)知識(shí),感興趣的朋友一起看看吧2022-03-03
JS+DIV實(shí)現(xiàn)鼠標(biāo)劃過切換層效果的實(shí)例代碼
這篇文章主要是對JS+DIV實(shí)現(xiàn)鼠標(biāo)劃過切換層效果的實(shí)例代碼進(jìn)行了詳細(xì)的介紹,需要的朋友可以過來參考下,希望對大家有所幫助2013-11-11

