云匠網(wǎng)的美工靠譜嗎石家莊seo全網(wǎng)營銷
day31
購物車案例
一、加入購物車
? ? ? 1、點(diǎn)擊按鈕后,把當(dāng)前這個(gè)列表的數(shù)據(jù)拿到,應(yīng)該存儲(chǔ)到一個(gè)數(shù)組里面 --- 數(shù)據(jù)結(jié)構(gòu),把數(shù)據(jù)存儲(chǔ)進(jìn)行數(shù)組2、假如已經(jīng)把所有的數(shù)據(jù)添加數(shù)組完畢,最終應(yīng)該存儲(chǔ)進(jìn)購物車?yán)锩?#xff0c;所謂的購物車說白了最終還是得從localStorage里面獲取數(shù)據(jù) --- 兩個(gè)頁面數(shù)據(jù)共享(localStorage)3、當(dāng)點(diǎn)擊后按鈕,怎么把當(dāng)前這個(gè)列表的數(shù)據(jù)拿到呢?=> find() 通過這個(gè)查找數(shù)據(jù)=> 可以把數(shù)據(jù)的id綁定給按鈕標(biāo)記(通過自定義屬性)=> H5新增了一種自定義屬性的方式4、加入購物車的數(shù)據(jù),應(yīng)該先從購物車?yán)锩娅@取,應(yīng)該在已經(jīng)有的數(shù)據(jù)的基礎(chǔ)上進(jìn)行操作5、判斷下這個(gè)數(shù)組是否為空,如果為空就添加。如果不為空,就要查看是否有重復(fù)的數(shù)據(jù)
利用面向?qū)ο髞韺慾s
? ?class List {constructor(){this.ul = document.querySelector('ul')this.span = document.querySelector('span') ?// 需要操作的數(shù)據(jù)this.data = product_listthis.init()this.totalCount()}init(){this.render()this.bindEvent()}render(){this.data.forEach(item=>{this.ul.innerHTML += `<li><div class="pic"><img src="${item.url}"></div><p class="title">${item.title}</p><p class="des">${item.des}</p><p class="price">${item.price}</p><button data-id=${item.id}>加入購物車</button></li>`})}// 由于按鈕需要綁定很多次事件,最簡單的可以使用事件委派bindEvent(){this.ul.addEventListener('click', (e)=>{// 獲取事件目標(biāo)對(duì)象 nodeType nodeValue nodeNamelet t = e.targetif(t.nodeName === 'BUTTON'){// 獲取當(dāng)前按鈕的自定義屬性let id = t.dataset.id - 0// 使用find方法拿到當(dāng)前的數(shù)據(jù)let goods = this.data.find(item=> item.id === id)// 聲明一個(gè)數(shù)組用來存儲(chǔ)當(dāng)前的列表數(shù)據(jù) --- 人為規(guī)定:存儲(chǔ)進(jìn)行l(wèi)ocalStorage里面的數(shù)據(jù)名稱,叫做cart// 加入購物車的數(shù)據(jù),應(yīng)該先從購物車?yán)锩娅@取,應(yīng)該在已經(jīng)有的數(shù)據(jù)的基礎(chǔ)上進(jìn)行操作// 注意點(diǎn):從localStorage里面如果沒有拿到數(shù)據(jù)外界返回的是null,null使用JSON.parse()不會(huì)報(bào)錯(cuò),返回的還是null// 沒有就返回一個(gè)空的數(shù)組,把數(shù)據(jù)添加行這個(gè)數(shù)組let list = JSON.parse(localStorage.getItem('cart')) || []// 判斷數(shù)組是否為空if(!list.length){goods.cart_num = 1list.push(goods)}else{// 進(jìn)到這里說明已經(jīng)有數(shù)據(jù)了,那么應(yīng)該判斷下這個(gè)數(shù)組里面是否有相同的數(shù)據(jù)// some() --- 查看數(shù)組是否有滿足條件的,如果有就直接返回truelet res = list.some(item=>item.id === id)// 如果有重復(fù)的,應(yīng)該把這個(gè)數(shù)據(jù)從數(shù)組里面獲取出來,把數(shù)據(jù)的cart_num數(shù)量自增if(res){let index = list.findIndex(item=>item.id === id)list[index].cart_num++}else{// 說明沒有重復(fù)的,把數(shù)據(jù)添加進(jìn)行數(shù)組goods.cart_num = 1list.push(goods)}}// 應(yīng)該把數(shù)據(jù)存儲(chǔ)進(jìn)行l(wèi)ocalStorage里面localStorage.setItem('cart', JSON.stringify(list))// 每次重復(fù)存儲(chǔ)的時(shí)候,讓其再次調(diào)用計(jì)算this.totalCount()}})}totalCount(){let list = JSON.parse(localStorage.getItem('cart')) || []let num = 0list.forEach(item=> num += item.cart_num)this.span.innerHTML = num} ?}new List()
二、購物車界面:
也是利用面向?qū)ο髞硗瓿蒵s部分
? ?class Cart {constructor(){// 從localStorage里面獲取到購物車?yán)锩娴臄?shù)據(jù)this.list = JSON.parse(localStorage.getItem('cart')) || []// 聲明變量作為價(jià)格的處理this.price = 0// 獲取元素this.tbody = document.querySelector('tbody')this.footer = document.querySelector('.footer')this.cartTable = document.querySelector('.cartTable')this.init()}init(){this.render()this.bindEvent()}render(){let totalNum = 0let totalPrice = 0// 如果沒有數(shù)據(jù),那么就給用戶一個(gè)提示,讓其跳轉(zhuǎn)到加入購物車的頁面if(!this.list.length){this.tbody.innerHTML = `<tr height="100"><td colspan="6"><h1>您的購物車空空如也!趕緊去購物<a href="./02_加入購物車.html">Go...</a></h1> ? ?</td></tr>`}else{// 如果重復(fù)調(diào)用render函數(shù)的話,那么就應(yīng)該把之前的數(shù)據(jù)清除,根據(jù)新的數(shù)據(jù)重新添加this.tbody.innerHTML = ''// 如果有數(shù)據(jù),那么就根據(jù)購物車?yán)锩娴臄?shù)據(jù)進(jìn)行列表渲染this.list.forEach(item=>{// item.is_select表示復(fù)選框是否選中的狀態(tài)this.tbody.innerHTML += `<tr><td><input type="checkbox" value="" class="select" ${item.is_select && "checked"} data-id=${item.id}></td><td><img src="${item.url}" ><span style="font-size:14px;">${item.title}</span></td><td><span>${item.price}</span></td><td><button class="sub" data-id=${item.id}>-</button><input type="text" value="${item.cart_num}" class="count"><button class="add" data-id=${item.id}>+</button></td><td><span class="price">${item.cart_num * item.price}元</span></td><td><span class="del" data-id=${item.id}>刪除</span></td></tr>`// 計(jì)算商品的種類的件數(shù)// if(item.is_select){// ? ? totalNum++// } ?// 計(jì)算商品總的件數(shù)if(item.is_select){totalNum += item.cart_numtotalPrice += item.cart_num * item.price}})}// 決定全選復(fù)選框的狀態(tài)let _state = this.list.every(item=> item.is_select)// 判斷下數(shù)組是否為空if(!this.list.length){_state = false}// 全選復(fù)選框的狀態(tài)是由單選的復(fù)選框來決定的this.footer.innerHTML = `<div class="left"><input type="checkbox" value="" class="allCheck" ${_state && "checked"}/><span class="dlAll">刪除</span></div><div class="rirght"><div class="allNum">已選商品<b class="totalNum">${totalNum}</b>件</div><div class="allCount">合計(jì) ¥<b class="money">${totalPrice.toFixed(2)}</b>元</div><div class="calc">結(jié)算</div></div>`// 數(shù)據(jù)持久化localStorage.setItem('cart', JSON.stringify(this.list))this.price = totalPrice.toFixed(2)}// 開發(fā)思想數(shù)據(jù)驅(qū)動(dòng)視圖:當(dāng)數(shù)據(jù)改變了,那么界面就跟著改變(重新渲染),你只需要操作數(shù)據(jù)即可。這種思想目前在vue、react里面是非常常見的bindEvent(){this.cartTable.addEventListener('click', e=>{let t = e.targetif(t.className === 'allCheck'){// 獲取全選復(fù)選框的狀態(tài)let state = t.checkedthis.list.forEach(item=>{item.is_select = state})// 當(dāng)數(shù)據(jù)改變了,根據(jù)改變后的數(shù)據(jù)重新渲染一次頁面即可this.render()}if(t.className === 'select'){// 當(dāng)點(diǎn)擊單選復(fù)選框的時(shí)候,應(yīng)該先把當(dāng)前這條數(shù)據(jù)拿到,再把這個(gè)數(shù)據(jù)的選中狀態(tài)給改變// 拿到單選框的自定義idlet id = t.dataset.id - 0let goods = this.list.find(item=>item.id === id)goods.is_select = !goods.is_selectthis.render()}if(t.className === 'add'){let id = t.dataset.id - 0let goods = this.list.find(item=>item.id === id)// 注意點(diǎn):最多可以購買多少件商品,這里需要判斷是是否已經(jīng)達(dá)到庫存的數(shù)量,而不是固定數(shù)量寫法if(goods.cart_num >= 10){alert('限購10件')return}goods.cart_num++this.render()}if(t.className === 'sub'){let id = t.dataset.id - 0let goods = this.list.find(item=>item.id === id)if(goods.cart_num === 1){return }goods.cart_num--this.render()}// 單個(gè)刪除if(t.className === 'del'){let id = t.dataset.id - 0let index = this.list.findIndex(item=>item.id === id)// splice shift pop ?this.list.splice(index, 1)this.render()}// 全選刪除if(t.className === 'dlAll'){let newList = this.list.filter(item=> item.is_select === false)this.list = newListthis.render()}if(t.className === 'calc'){// sessionStorage.setItem('price', this.price)location.href = `./04_結(jié)算頁面.html?${this.price}`}})}}new Cart()
三、結(jié)算頁面
<h1>結(jié)算頁面</h1> <script>console.log(location.search.slice(1)) </script>