1.JSON的两个API
前后端交互原理:
1.从html页面得到数据
2.将数据转为json字符串JSON.stringify(data)
,将json字符串发送给后端
3.后端将数据转为后端的对象或数组,处理后保存到数据库
4.得到数据库的数据后,通过后端的函数把数据转为json字符串发送给前端
5.前端收到json字符串,通过JSON.parse(jsonString)
把JSON字符串转为js对象
6.转为js对象处理后,可以通过dom树操作挂载给html页面
优点:
1.数据格式简单,易读写,所以它的语法小而轻,数据交互时解析时间快,页面响应时间也更快,占用带宽小
2.兼容性更广泛,目前几乎是互联网上通用的数据交互方式,各大平台和浏览器都支持json传输方式,支持多种语言
// 声明对象
let obj= {
id: 1,
name: "张三",
email: "zhangsan@163.com",
addr: "贵阳观山湖",
};
console.log('js对象: ',obj);
// 1.将js对象序列化 发送到前段
console.log('序列化对象后的json字符串: ', JSON.stringify(obj));
// 2.将序列化js对象的值模拟为后端发送的json字符串
// 后端数据
let phpObj = JSON.stringify(obj);
// 3.将后端数据反序列化
console.log('将后端的json字符串反序列化为js对象: ', JSON.parse(phpObj));
2.实战-购物车
效果图:
代码:
<header>
<span>购物车</span>
</header>
<main>
<div class="goods">
<div class="item">
<input type="checkbox" class="selectOne" onchange="selectOne(this)" id="selectOne" checked />
<img src="static/iamage/1.jpeg" alt="" />
<span class="title">联想ThinkBook Plus 17 双屏轻薄本 英特尔酷睿i7 17.3英寸 i7-12700H 16G 512G</span>
<div class="count">
<input type="number" value="1" min="1" class="num" />
<span class="priceTag">单价: <span class="price">100</span>元</span>
<span class="amountTag">小计: <span class="amount">0</span>元</span>
</div>
</div>
</main>
<footer>
<div class="left">
<input type="checkbox" onchange="selectAll(this)" class="selectAll" id="slectAll" checked />
<span>全选</span>
</div>
<span>
已选<span class="nums">0</span>件,
<span>合计</span>
<span style="color: red">¥</span>
<span class="totalAmount">0</span>
<span>元</span>
</span>
<button>领劵结算</button>
</footer>
@import url("reset.css");
body header {
width: 100%;
height: 0.4rem;
background-color: white;
position: fixed;
left: 0;
top: 0;
box-shadow: 0.02rem 0.02rem 0.5rem rgba(0, 0, 0, 0.2);
}
body header span {
display: block;
font-size: larger;
font-weight: bold;
text-align: center;
line-height: 0.4rem;
}
body footer {
width: 100%;
height: 0.8rem;
background-color: white;
position: fixed;
left: 0;
bottom: 0;
display: flex;
place-content: space-between;
padding: 0 0.2rem;
line-height: 0.8rem;
gap: 0 10px;
}
body footer span {
color: #888;
}
body footer span:last-of-type span:nth-of-type(1),
body footer span:last-of-type span:nth-of-type(4) {
font-size: x-large;
color: red;
}
body footer span:last-of-type span:nth-of-type(2),
body footer span:last-of-type span:last-of-type {
color: #000;
}
body footer .left {
margin-top: 0.04rem;
}
body footer button {
width: 1rem;
height: 0.5rem;
margin: auto;
background-color: red;
border: none;
border-radius: 0.3rem;
padding: 0.05rem;
color: white;
font-weight: bold;
}
body main {
margin-top: 0.5rem;
padding: 0 0.15rem;
}
body main .goods {
margin: auto;
display: flex;
flex-wrap: wrap;
gap: 0.2rem 0;
padding-bottom: 1rem;
}
body main .goods .item {
padding: 0 0.1rem;
width: 100%;
height: 1rem;
border-radius: 00.1rem;
background-color: white;
box-shadow: 0.02rem 0.02rem 0.05rem rgba(0, 0, 0, 0.5);
display: grid;
grid-template-columns: 0.2rem 1rem 1fr;
grid-template-rows: 1fr 0.4rem;
gap: 0 0.1rem;
place-items: center;
}
body main .goods .item input[type="checkbox"] {
grid-row: span 2;
}
body main .goods .item img {
width: 0.9rem;
grid-row: span 2;
border-radius: 0.04rem;
}
body main .goods .item .title {
width: 100%;
place-self: center start;
font-size: x-small;
}
body main .goods .item .count {
width: 100%;
display: flex;
place-content: space-between;
}
body main .goods .item .count .price,
body main .goods .item .count .amount {
font-size: large;
color: red;
}
body main .goods .item input[type="number"] {
width: 0.5rem;
border: none;
outline: none;
text-align: center;
/* font-size: 1em; */
background-color: transparent;
}
// 得到所有复选框
let checkItems = document.querySelectorAll(".selectOne");
/* 全选按钮 */
selectAll = (ele) => {
// 得到全选按钮的状态
let status = ele.checked;
// 找到商品列表中所有的复选框,并将全选框的状态赋予列表中的复选框
document.querySelectorAll(".selectOne").forEach((item) => (item.checked = status));
autoCalculate();
};
/* 根据用户的选择来动态的设置"全选"按钮的状态 */
selectOne = (ele) => {
// every()当满足所有条件时才返回ture 且数组的方法 必须转为数组
document.querySelector(".selectAll").checked = [...checkItems].every(
(item) => item.checked === true
);
autoCalculate();
};
// 得到商品的数量元素
const nums = document.querySelectorAll(".goods .item .num");
// 计算商品总数
// reduce(acc,cur):自动计算 累加
getTotalNum = (numsArr) => (numsArr.length === 0 ? 0 : numsArr.reduce((acc, cur) => acc + cur));
//计算每件商品的价格
getOneAmount = (numsArr, priceArr) => {
return numsArr.map((item, index) => item * priceArr[index]);
};
// 计算总金额
getTotalAmount = (amountArr) =>
amountArr.length === 0 ? 0 : amountArr.reduce((acc, cur) => acc + cur);
// 自动计算
autoCalculate = () => {
// 1. 页面初始的小计、总计数量及总价
// 得到所有数量
let numArr = [...checkItems].map((item) =>
parseInt(item.parentElement.children[3].children[0].value)
);
// 得到单价类数组
let prices = document.querySelectorAll(".goods .item .count .price");
// 得多所有商品的价格
let priceArr = [...prices].map((item) => item.textContent);
// 给每件商品做小计 单价*价格
// getOneAmount()得到金额数组
let amountArr = getOneAmount(numArr, priceArr);
// 给每个小计标签遍历赋值 将计算的小计添加到页面
document
.querySelectorAll(".goods .item .count .amount")
.forEach((item, i) => (item.textContent = amountArr[i]));
// 2. checked=ture情况下的小计、总计数量及总价
// 得到只有选中状态的复选框
let newCheckItems = [...checkItems].filter((item) => item.checked === true);
// 只计算check为true的 数量总和
let numArrTure = [...newCheckItems].map((item) =>
parseInt(item.parentElement.children[3].children[0].value)
);
// 将计算的商品总数量添加到页面
document.querySelector("footer .nums").textContent = getTotalNum(numArrTure);
// 填充总金额
// 只计算check为true的 小计金额
let amountArrTure = newCheckItems.map((item) =>
parseInt(item.parentElement.children[3].children[2].children[0].textContent)
);
document.querySelector("footer .totalAmount").textContent = getTotalAmount(amountArrTure);
};
// 页面加载时自动计算购物车的数量、小计、总计
window.onload = autoCalculate;
// 当用户更新商品数量时, 将会触发数量、小计、总计的动态更新
nums.forEach((item) => (item.onchange = autoCalculate));