关于HarmonyOS的学习
day31
购物车案例
一、加入购物车
1、点击按钮后,把当前这个列表的数据拿到,应该存储到一个数组里面 --- 数据结构,把数据存储进行数组2、假如已经把所有的数据添加数组完毕,最终应该存储进购物车里面,所谓的购物车说白了最终还是得从localStorage里面获取数据 --- 两个页面数据共享(localStorage)3、当点击后按钮,怎么把当前这个列表的数据拿到呢?=> find() 通过这个查找数据=> 可以把数据的id绑定给按钮标记(通过自定义属性)=> H5新增了一种自定义属性的方式4、加入购物车的数据,应该先从购物车里面获取,应该在已经有的数据的基础上进行操作5、判断下这个数组是否为空,如果为空就添加。如果不为空,就要查看是否有重复的数据
利用面向对象来写js
class List {constructor(){this.ul = document.querySelector('ul')this.span = document.querySelector('span') // 需要操作的数据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)=>{// 获取事件目标对象 nodeType nodeValue nodeNamelet t = e.targetif(t.nodeName === 'BUTTON'){// 获取当前按钮的自定义属性let id = t.dataset.id - 0// 使用find方法拿到当前的数据let goods = this.data.find(item=> item.id === id)// 声明一个数组用来存储当前的列表数据 --- 人为规定:存储进行localStorage里面的数据名称,叫做cart// 加入购物车的数据,应该先从购物车里面获取,应该在已经有的数据的基础上进行操作// 注意点:从localStorage里面如果没有拿到数据外界返回的是null,null使用JSON.parse()不会报错,返回的还是null// 没有就返回一个空的数组,把数据添加行这个数组let list = JSON.parse(localStorage.getItem('cart')) || []// 判断数组是否为空if(!list.length){goods.cart_num = 1list.push(goods)}else{// 进到这里说明已经有数据了,那么应该判断下这个数组里面是否有相同的数据// some() --- 查看数组是否有满足条件的,如果有就直接返回truelet res = list.some(item=>item.id === id)// 如果有重复的,应该把这个数据从数组里面获取出来,把数据的cart_num数量自增if(res){let index = list.findIndex(item=>item.id === id)list[index].cart_num++}else{// 说明没有重复的,把数据添加进行数组goods.cart_num = 1list.push(goods)}}// 应该把数据存储进行localStorage里面localStorage.setItem('cart', JSON.stringify(list))// 每次重复存储的时候,让其再次调用计算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()
二、购物车界面:
也是利用面向对象来完成js部分
class Cart {constructor(){// 从localStorage里面获取到购物车里面的数据this.list = JSON.parse(localStorage.getItem('cart')) || []// 声明变量作为价格的处理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// 如果没有数据,那么就给用户一个提示,让其跳转到加入购物车的页面if(!this.list.length){this.tbody.innerHTML = `<tr height="100"><td colspan="6"><h1>您的购物车空空如也!赶紧去购物<a href="./02_加入购物车.html">Go...</a></h1> </td></tr>`}else{// 如果重复调用render函数的话,那么就应该把之前的数据清除,根据新的数据重新添加this.tbody.innerHTML = ''// 如果有数据,那么就根据购物车里面的数据进行列表渲染this.list.forEach(item=>{// item.is_select表示复选框是否选中的状态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>`// 计算商品的种类的件数// if(item.is_select){// totalNum++// } // 计算商品总的件数if(item.is_select){totalNum += item.cart_numtotalPrice += item.cart_num * item.price}})}// 决定全选复选框的状态let _state = this.list.every(item=> item.is_select)// 判断下数组是否为空if(!this.list.length){_state = false}// 全选复选框的状态是由单选的复选框来决定的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">合计 ¥<b class="money">${totalPrice.toFixed(2)}</b>元</div><div class="calc">结算</div></div>`// 数据持久化localStorage.setItem('cart', JSON.stringify(this.list))this.price = totalPrice.toFixed(2)}// 开发思想数据驱动视图:当数据改变了,那么界面就跟着改变(重新渲染),你只需要操作数据即可。这种思想目前在vue、react里面是非常常见的bindEvent(){this.cartTable.addEventListener('click', e=>{let t = e.targetif(t.className === 'allCheck'){// 获取全选复选框的状态let state = t.checkedthis.list.forEach(item=>{item.is_select = state})// 当数据改变了,根据改变后的数据重新渲染一次页面即可this.render()}if(t.className === 'select'){// 当点击单选复选框的时候,应该先把当前这条数据拿到,再把这个数据的选中状态给改变// 拿到单选框的自定义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)// 注意点:最多可以购买多少件商品,这里需要判断是是否已经达到库存的数量,而不是固定数量写法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()}// 单个删除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_结算页面.html?${this.price}`}})}}new Cart()
三、结算页面
<h1>结算页面</h1> <script>console.log(location.search.slice(1)) </script>