先写查
=> 先使用数据把页面渲染出来
=> 当你删除的时候, 只要从原始数组中把某一条数据删除, 从新渲染页面
1. 根据 list 数组把 购物车 页面渲染好
1-1. 准备一个函数, 用作渲染页面
1-2. 开始循环遍历数组渲染数据
=> 问题: 什么位置需要渲染 ?
=> 把所有购物车相关的内容都渲染出来
1-3. 根据数组中的数据, 去渲染 ul 中的 li
=> 数组里面有多少数据, ul 里面就有多少个 li
1-4. 渲染 顶部 和 底部 的所有数据
=> 需要计算一些数据来进行渲染
=> 总价格: 所有选中的商品的小计价格之和
=> 总购买数量: 所有选中商品的购买数量之和
=> 全选按钮: 是否选中, 所有商品都选中, 才选中
2. 绑定事件
+ 观察事件类型:
=> 全选按钮: 点击
=> 每一个商品的选中: 点击
=> 每个商品的数量增加: 点击
=> 每个商品的数量减少: 点击
=> 每个商品的删除: 点击
=> 去结算: 点击
=> 清空购物车: 点击
=> 删除所有已选中: 点击
=> 返回列表页: 点击
+ 观察事件结构
=> 有一个共同的父级吗 ?
=> content 元素
+ 决定事件事件委托方式 ?
=> 把事件绑定在 content 元素身上
=> 通过事件目标判断点击的是 某一个 准确的元素
<div class="content">
<!-- 依靠 JS 渲染 -->
</div>
// 0. 获取元素
let content = document.querySelector('.content')
// 1. 渲染页面
// 1-1. 准备一个函数
bindHtml()
let bindHtml = () => {
// 1-4. 根据 list 计算一些数据
// 总价格,总购买数量,复选框勾选数量
var totalPrice = 0, totalNum = 0, selectNum = 0
// 遍历数组
list.forEach(item => {
if (item.select === true) {
totalPrice += item.price * item.buy_num
totalNum += item.buy_num
selectNum++
}
})
// 1-2. 准备渲染
let str = `
<div class="top">
<input class="select_all" type="checkbox" ${ selectNum >= list.length ? 'checked' : '' }> 全选
</div>
<ul class="center">
`
// 1-3. 根据数组生成 li
list.forEach(item => {
str += `
<li>
<div class="select">
<input data-id="${ item.id }" class="select_one" type="checkbox" ${ item.select ? 'checked' : '' }>
</div>
<div class="pic">
<img src="${ item.pic }" alt="">
</div>
<div class="name">
${ item.name }
</div>
<div class="price">
¥ <span>${ (item.price - 0).toFixed(2) }</span>
</div>
<div class="number">
<button data-id="${ item.id }" class="sub">-</button>
<input type="text" value="${ item.buy_num }">
<button data-id="${ item.id }" class="add">+</button>
</div>
<div class="subtotal">
¥ <span>${ (item.price * item.buy_num).toFixed(2) }</span>
</div>
<div class="del">
<button data-id="${ item.id }" class="del_btn">删除</button>
</div>
</li>
`
})
str += `
</ul>
<div class="bottom">
<p>总购买数量: ${ totalNum }</p>
<p>
<button data-price="${ totalPrice }" class="pay">去结算</button>
<button class="clear">清空购物车</button>
<button class="clear_select">删除所有已选中</button>
<button class="list">返回列表页</button>
</p>
<p>总价格 : ¥ <span>${ totalPrice.toFixed(2) }</span></p>
</div>
`
// 直接把准备好的 str 放在 content 中
content.innerHTML = str
}
// 2. 绑定事件
content.addEventListener('click', e => {
// 处理事件对象兼容
e = e || window.event
// 处理事件目标兼容
let target = e.target || e.srcElement
// 2-2. 通过 target 来判断你点击的是哪一个按钮
// 判断点击的是全选
if (target.className === 'select_all') {
// 1. 拿到自己是 true 还是 false
// 自己是什么 ? target
let type = target.checked
// 2. 赋值
// 拿到的是 true, list 里面每一项的 select 都应该变成 true
// 拿到的是 false, list 里面每一项的 seletc 都应该变成 false
list.forEach(item => { item.select = type })
// 3. 从新渲染页面
bindHtml()
}
// 判断点击的是每一个商品的选项按钮
if (target.className === 'select_one') {
// 1. 拿到自己应该修改数组中的哪一条数据
// 在渲染页面的时候, 把自己这一条数据的 id 渲染在标签身上
// 如果想让整个购物车结构联动, 必须要把 list 中的数据修改
// 该哪一条数据 ?
// 你点的是 第一个 li, 改哪一个数据
// 在渲染页面的时候, 把数据的 id 渲染在标签身上
let id = target.dataset.id - 0
// 2. 在 list 中找到数组中和 id 一样的哪一条数据
let goods = list.find(item => item.id === id )
// 3. 把内容修改掉
goods.select = !goods.select
// 4. 渲染页面
bindHtml()
}
// 判断点击的是每一个商品的数量减少
if (target.className === 'sub') {
// 1. 拿到自己身上记录的 id
let id = target.dataset.id - 0
// 2. 找到指定的数据
let goods = list.find(item => item.id == id )
// 3. 判断一下是否已经是 1
if (goods.buy_num <= 1) return
goods.buy_num--
// 4. 渲染页面
bindHtml()
}
// 判断点击的是每一个商品的数量增加
if (target.className === 'add') {
// 1. 拿到自己身上的 id
let id = target.dataset.id - 0
// 2. 找到指定数据
let goods = list.find(item => item.id === id )
// 3. 判断, 别超过库存
if (goods.buy_num >= goods.number) return
goods.buy_num++
// 4. 从新渲染页面
bindHtml()
}
// 判断点击的是每一个商品的删除按钮
if (target.className === 'del_btn') {
// 1. 拿到自己身上的 id
let id = target.dataset.id - 0
// 2. 从 list 数组中删除 id 对应的数据
// filter
list = list.filter(item => item.id !== id )
// 3. 从新渲染页面
bindHtml()
}
// 判断点击的是去结算
if (target.className === 'pay') {
// 1. 拿到应该支付的总价
let price = target.dataset.price - 0
// 2. 提示用户
window.alert(`您需要支付 ${ price.toFixed(2) } 元人民币, 点击确定跳转到支付页面 ^_^`)
}
// 判断点击的是清空购物车
if (target.className === 'clear') {
// 1. 把 list 变成一个空数组
list = []
// 2. 从新渲染页面
bindHtml()
}
// 判断点击的是删除所有已选中
if (target.className === 'clear_select') {
// 1. 把 list 里面所有的 select 为 true 的都删除
// 把 list 里面所有 select 为 false 的留下
list = list.filter(item => item.select === false )
// 2. 渲染页面
bindHtml()
}
// 判断点击的是返回列表页
if (target.className === 'list') {
window.location.href = 'https://www.baidu.com'
}
})