index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="css/index.css">
</head>
<body>
<header>网页头部区域</header>
<main>
<ul></ul>
</main>
<a href="html/cart.html">
<div class="count">
商品共<span>0</span>件
</div>
</a>
<!--json数据格式不能直接使用js文件引用,必须通过ajax请求-->
<script src="js/ajax.js"></script>
<script src="js/index.js"></script>
</body>
</html>
index.js
class List{
constructor() {
//获取元素
this.container = document.querySelector('ul')
this.span = document.querySelector('span')
this.init()
}
init() {
this.request()
//注意点:data数据是发送请求获取到的,在初始化的时候直接调用代码,异步代码是没有返回结果的所以是undefined
// this.cart()
this.count()
}
request() {
pAjax({url: 'data/goods.json'})
.then((res)=>{
let data = JSON.parse(res)
data = data.slice(0, 60)
this.render(data)
this.cart(data)
})
}
render(data) {
data.forEach((item) => {
//html/details.html?id=${item.goods_id}在查询字符串后面进行参数拼接,可以让网页跳转的时候把需要的参数携带到另一个网页
this.container.innerHTML += `
<li>
<a href="html/details.html?id=${item.goods_id}" style="text-decoration:none; color:black;">
<div class="pic">
<img src="${item.img_small_logo}">
</div>
<p class="title hide">${item.title}</p>
<p class="price">${item.price}</p>
</a>
<button data-id=${item.goods_id}>加入购物车</button>
</li>
`
})
}
cart(data){
//做事件委派
this.container.addEventListener('click', (e) => {
e = e || window.event
let target = e.target || e.srcElement
//判断是否点击的是按钮
if (target.nodeName == 'BUTTON') {
//获取到每一个按钮的id
let id = target.dataset.id - 0
//当咱们点击对应的按钮的时候,获取到相应那条数据
let goods = data.find((item) => { return item.goods_id == id })
//先获取下购物车里面有没有数据,如果没有数据让它返回一个空数组
let list = JSON.parse(localStorage.getItem('cart')) || []
//判断里面有没有数据
if (!list.length) {
//没有数据,如果能进到这个地方说明就是没有数据的
//没有数据,应该先把数据添加进数组,并让商品数量赋值为1
list.push(goods)
goods.cart_number = 1
} else {
//如果有数据,先判断下数组里面有没有这条数据,防止重复存在
let res = list.some((item) => { return item.goods_id == id })
//如果数据相同,应该找到相同的数据让其商品数量自增+1
if (res) {
let index = list.findIndex((item) => { return item.goods_id == id })
list[index].cart_number++
} else {
//没有相同的,就把数据添加进数组
list.push(goods)
goods.cart_number = 1
}
}
//把对应的数据应该存储进购物车里面
localStorage.setItem('cart', JSON.stringify(list))
//当咱们点击按钮的时候,让商品数量进行变化
this.count()
}
}, false)
}
count() {
//先从购物车里面把数据提取出来
let list = JSON.parse(localStorage.getItem('cart')) || []
let num = 0
//遍历进行数量增加
list.forEach((item) => {
num += item.cart_number
})
//给span标记进行赋值操作
this.span.innerHTML = num
}
}
new List()
cart.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="../css/cart.css">
</head>
<body>
<div class="cartTable">
<table>
<thead>
<tr>
<th>全选</th>
<th>商品</th>
<th>单价</th>
<th>数量</th>
<th>小计</th>
<th>操作</th>
</tr>
</thead>
<tbody></tbody>
</table>
<div class="footer">
<div class="left">
<input type="checkbox" value="" class="selectAll" />
<span class="dlAll">删除</span>
</div>
<div class="rirght">
<div class="allNum">已选商品<b class="totalNum">0</b>件</div>
<div class="allCount">合计 ¥<b class="money">0</b></div>
<!---当咱们点击结算标记的时候,使用存储方式在本地进行保存,当跳到支付页面的时候再获取出来渲染页面-->
<a href="total.html">
<div class="calc">结算</div>
</a>
</div>
</div>
<script src="../js/cart.js"></script>
</body>
</html>
cart.js
class Cart{
constructor() {
//获取元素
this.cartTable = document.querySelector('.cartTable')
this.tbody = document.querySelector('tbody')
this.totalNum = document.querySelector('.totalNum')
this.money = document.querySelector('.money')
this.selectAll = document.querySelector('.selectAll')
//获取数据
this.data = JSON.parse(localStorage.getItem('cart')) || []
//调用init方法
this.init()
}
init(){
this.render()
this.bindHtml()
this.total()
}
//根据数据渲染页面
render() {
this.tbody.innerHTML = ''
//思考:列表页面如果添加了商品,购物车里面就有数据,如果没有添加就没有数据
if (!this.data.length) {
//如果没有数据就进入这里,给用户一个提示
this.tbody.innerHTML = `
<tr height="100">
<td colspan="6">
<h1>您的购物车空空如也! 赶紧去购物吧<a href="../_index.html">Go</a></h1>
</td>
</tr>
`
} else {
this.data.forEach(item => {
this.tbody.innerHTML += `
<tr>
<td><input type="checkbox" value="" class="select" data-id="${item.goods_id}" ${item.is_select && "checked"}/></td>
<td>
<img src="${item.img_small_logo}">
<span class="hide">${item.title}</span>
</td>
<td><span class="price">${item.price}</span></td>
<td>
<span class="sub" data-id="${item.goods_id}">-</span>
<input type="text" value="${item.cart_number}" class="txt" data-id="${item.goods_id}" />
<span class="add" data-id="${item.goods_id}">+</span>
</td>
<td><span class="subTotal">${item.cart_number * item.price}元</span></td>
<td><span class="del" data-id="${item.goods_id}">删除</span></td>
</tr>
`
})
}
//数据持久化
localStorage.setItem('cart', JSON.stringify(this.data))
}
//给html绑定各种事件
bindHtml() {
//做事件委派
this.cartTable.addEventListener('click', (e) => {
//事件对象兼容写法
e = e || window.event
//事件(目标事件)源兼容写法
let target = e.target || e.srcElement
//做全选功能
if (target.className == 'selectAll') {
console.log(this.data)
//获取全选按钮的状态
let type = target.checked
//当咱们点击全选按钮的时候,让所有的单选按钮选中或未选中
//思路:使用数据驱动页面,修改的是数组
this.data.forEach(item => {
item.is_select = type
})
//当咱们把数据修改了应该重新渲染页面
this.render()
this.total()
}
//单选功能
//注意点:在服务器环境下,很多的数据会进行缓存,所以当有时候有些数据会从浏览器缓存里面获取,会导致代码出错
if (target.className == 'select') {
let id = target.dataset.id - 0
let goods = this.data.find(item => { return item.goods_id == id })
//改变选中状态
goods.is_select = !goods.is_select
//渲染页面
this.render()
this.total()
}
//点击数量增加
if (target.className == 'add') {
let id = target.dataset.id - 0
let goods = this.data.find(item => { return item.goods_id == id })
if (goods.cart_number == goods.goods_number) {
alert('亲,只能买这么多!')
return false
}
goods.cart_number ++
//渲染页面
this.render()
this.total()
}
//点击数量减少
if (target.className == 'sub') {
let id = target.dataset.id - 0
let goods = this.data.find(item => { return item.goods_id == id })
if (goods.cart_number == 1) {
return false
}
goods.cart_number--
//渲染页面
this.render()
this.total()
}
//删除操作
if (target.className == 'del') {
let id = target.dataset.id - 0
//注意点:返回的是在数组里面的位置
let index = this.data.findIndex(item => { return item.goods_id == id })
this.data.splice(index, 1)
//如果数组是空的,把全选框的状态改为false
if (!this.data.length) {
this.selectAll.checked = false
}
//渲染页面
this.render()
this.total()
}
//清空购物车
if (target.className == 'dlAll') {
//如果都是true的状态说明都是选中的,把你给过滤掉,只剩下状态是false的重新赋值
let res = this.data.filter(item => { return item.is_select == false })
this.data = res
//如果数组是空的,把全选框的状态改为false
if (!this.data.length) {
this.selectAll.checked = false
}
//渲染页面
this.render()
this.total()
}
}, false)
}
//计算总价和数量
total() {
//使用两个变量保存总的数量和总价格
let num = 0
let money = 0
//遍历数组
this.data.forEach(item => {
//当单选按钮是选中状态的时候应该计算
if (item.is_select == true) {
num += item.cart_number
money += item.cart_number * item.price
//当咱们单选框是选中的状态进行判断全选框是否选中
let res = this.data.every(item => { return item.is_select == true })
if (res) {
this.selectAll.checked = true
} else {
this.selectAll.checked = false
}
}
})
//进行赋值操作
this.totalNum.innerHTML = num
this.money.innerHTML = money
}
}
new Cart()
details.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="../css/details.css">
</head>
<body>
<header>这是网页头部区域</header>
<main>
<div class="con">
<div class="left">
<div class="pic">
<img src="" alt="" width="300" height="300">
</div>
<ul>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
</div>
<div class="right"></div>
</div>
<div class="dtl">
</div>
</main>
<script src="../js/ajax.js"></script>
<script src="../js/details.js"></script>
</body>
</html>
details.js
/*
详情页面逻辑
+ 当咱们在商品列表页面点击某个商品的时候,通过查询字符串的形式把商品id携带到详情页面
+ 先获取到商品id
+ 发送ajax请求
=> 把获取到的数据和id进行对比
=> 把相应的数据拿出来渲染页面
*/
class Details{
constructor() {
//获取元素
this.pic = document.querySelector('.pic>img')
this.dtl = document.querySelector('.dtl')
this.init()
}
init() {
this.request()
}
//查询字符串处理
queryStr(name) {
//?id=2&username=zhangsan
let str = location.search
let obj = {}
let arr = str.split('?')[1]
arr = arr.split('&')
arr.forEach(item => {
let newArr = item.split('=')
obj[newArr[0]] = newArr[1]
})
return obj[name]
}
//发送请求
request() {
let id = this.queryStr('id')
pAjax({ url: '../data/goods.json' })
.then(res => {
let data = JSON.parse(res)
data = data.slice(0, 60)
data.forEach(item => {
if (item.goods_id == id) {
this.render(item)
}
})
})
}
//渲染页面
render(data) {
//img_small_logo
//goods_introduce
// console.log(data)
this.pic.src = data.img_small_logo
this.dtl.innerHTML = data.goods_introduce
}
}
new Details()