选择卡示例购物车练习(逻辑有点跟不上,取消选择框重新计算价格没有写出来),又练习了幻灯片的制作
程序员文章站
2022-04-17 19:00:46
...
选择卡示例
重新复习了.filter返回条件的第一个元素(数组型)
重新复习了.find 返回符合条件的第一个元素
重新复习了.classList.remove 删除class元素
重新复习了.classList.add 增加元素
重新复习了.currentTarget 绑定者
重新复习了.target 触发者
重新复习了.Array.from 类数组转换
重新复习了[…类数组] 类数组转换
重新复习了.dataset.index 自定义元素
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>实战选择卡</title>
</head>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
div {
border: green 1px solid;
height: 20rem;
display: grid;
grid-template-rows: repeat(4, 1fr);
}
.head .heada {
display: none;
}
.head ul:first-of-type li {
clear: none;
float: left;
color: orange;
padding: 2px;
margin: 2px;
}
.head .heada.index {
display: block;
}
li {
list-style: none;
}
body {
display: grid;
}
.gaoliang {
background-color: green;
display: block;
}
a {
color: #fff;
}
div ul.heada.gaoliang {
display: block;
}
</style>
<body>
<div class="head">
<ul onclick="show()">
<li data-index="1" class="gaoliang">测试1</li>
<li data-index="2">测试2</li>
<li data-index="3">测试3</li>
</ul>
<ul class="heada index gaoliang" data-index="1">
<li><a href="#">选择卡1</a></li>
<li><a href="#">选择卡1</a></li>
<li><a href="#">选择卡1</a></li>
</ul>
<ul class="heada" data-index="2">
<li><a href="#">选择卡2</a></li>
<li><a href="#">选择卡2</a></li>
<li><a href="#">选择卡2</a></li>
</ul>
<ul class="heada" data-index="3">
<li><a href="#">选择卡3</a></li>
<li><a href="#">选择卡3</a></li>
<li><a href="#">选择卡3</a></li>
</ul>
</div>
<script>
function show() {
console.log(event);
// 当前事件绑定到了父级
console.log(event.currentTarget);
// 查看当前事件触发者
console.log(event.target);
const ul = event.currentTarget;
const li = event.target;
// 当点击某个标签时,其他标签取消高亮,当前标签变为高亮
// 先拿到当前ul绑定者的子级,触发者,
console.log(ul.children);
// 当前触发者是类数组,需要处理成数组
console.log([...ul.children]);
// 意思是拿到ul的子元素, 循环找到所有li标签, 删除所有的class属性值为gaoliang的
[...ul.children].forEach(li => li.classList.remove("gaoliang"));
// 这个地方意思就是触发者追加一个class属性值为gaoliang
li.classList.add("gaoliang");
/////////////////拿内容部分/////////////////
const uls = document.querySelectorAll(".heada");
console.log(uls);
const ulsa = Array.from(uls);
// 老实说不需要转换,都是数组形式,我已经转换完了,看了看
uls.forEach(li => li.classList.remove("gaoliang"));
// 然后转换成数组,之前我已经转换成ulsa了
// filter过滤器过滤满足条件的data-inedx的数据
// 把filter换成find拿到的是这个html节点
const content = [...ulsa].find(function (ul) {
return ul.dataset.index === li.dataset.index;
});
console.log(content);
// contents返回的值就是一个数组,一个成员的数组,换一个方法来
content.classList.add("gaoliang");
}
</script>
</body>
</html>
购物车跟老师写了一遍,加强了map,foreach两种遍历循环的认识,以及reduce叠加器认识,
虽然加强认识,但是总是感觉乱乱的,看到map一般是函数的返回上,但是foreach一般是填充到页面上.reduce累加器一般是计算结果,map或者把数组里面的索引拿出来单独用,还得强加联系
代码部分:
<!DOCTYPE html>
<html lang="zh-CN">
<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>实战:购物车计算</title>
<style>
.box {
width: 22em;
height: 2em;
}
.list > li {
height: 1.6em;
background-color: #efefef;
display: grid;
grid-template-columns: repeat(5, 3em);
gap: 1em;
place-items: center right;
border-bottom: 1px solid #ccc;
}
.list > li:first-of-type {
background-color: lightseagreen;
color: white;
}
.list > li:hover:not(:first-of-type) {
cursor: pointer;
background-color: lightcyan;
}
.list > li input[type="number"] {
width: 3em;
border: none;
outline: none;
text-align: center;
font-size: 1em;
background-color: transparent;
}
.list > li:last-of-type span.total-num,
.list > li:last-of-type span.total-amount {
grid-column: span 2;
place-self: center right;
color: lightseagreen;
}
.account {
float: right;
background-color: lightseagreen;
color: white;
border: none;
outline: none;
width: 4.5em;
height: 1.8em;
}
.account:hover {
background-color: coral;
cursor: pointer;
}
</style>
</head>
<body>
<div class="box">
<div class="selectAll">
<input type="checkbox" class="check-all" name="check-all" onchange="checkAll()" checked />
<label for="check-all">全选</label>
</div>
<ul class="list">
<li><span>选择</span><span>品名</span><span>数量</span><span>单价</span><span>金额</span></li>
<li>
<input type="checkbox" onchange="checkItems()" checked />
<span class="content">手机</span>
<input type="number" value="1" min="1" class="num" />
<span class="price">100</span>
<span class="amount">0</span>
</li>
<li>
<input type="checkbox" onchange="checkItems()" checked />
<span class="content">电脑</span>
<input type="number" value="2" min="1" class="num" />
<span class="price">200</span><span class="amount">0</span>
</li>
<li>
<input type="checkbox" onchange="checkItems()" checked />
<span class="content">相机</span>
<input type="number" value="3" min="1" class="num" />
<span class="price">300</span>
<span class="amount">0</span>
</li>
<li>
<span>总计:</span>
<span class="total-num">0</span>
<span class="total-amount">0</span>
</li>
</ul>
<button class="account">结算</button>
</div>
</body>
<script>
function checkAll() {
// 获取全选框的点击状态 返回true跟false
let ad = event.target.checked;
console.log(ad);
// 获取下面所有的全选框状态,根据主全选框动态设置子全选框
let zys = document.querySelectorAll(".list li input[type=checkbox]");
console.log(zys);
// 用forEach循环拿到数组zys的数组值,然后让ad的值全部给数组的值
zys.forEach(function (zhi) {
return (zhi.checked = ad);
});
}
function checkItems() {
let zys = document.querySelectorAll(".list li input[type=checkbox]");
console.log(zys);
// every判断
let quanxuan = [...zys].every(function (zhi) {
// 判断zhi.checked全部返回true则返回true 如果不是则返回fales
return zhi.checked === true;
});
// 把每个商品every返回的状态,给全选按钮
document.querySelector(".check-all").checked = quanxuan;
}
//////////////商品自动计算//////////////////////
const nums = document.querySelectorAll(".num");
console.log(nums);
console.log([...nums]);
// 购物车所有的数据计算依据是:基于商品的"数量"的变化
function zongshu(numArr) {
// acc是累加器,aur是当前数组的每一个值
return numArr.reduce(function (acc, cur) {
return acc + cur;
});
}
//////////////计算每个商品的总额///////////////
// 这里的函数 里面的两个值,都是一个数组,nuarr是数量,pricearr是单价
function getAmount(numArr, priceArr) {
// 这里那numarr当数组处理, map是数组的值 index是键 而pricearr对应了map里面值的键 所以map的键=pricearr的键
return numArr.map((num, index) => num * priceArr[index]);
}
///////////计算总金额//////////////
function getTotalAmount(amountArr) {
return amountArr.reduce((acc, cur) => acc + cur);
}
// 自动计算
function autoCalculate() {
// 数量数组 从class num中拿到数量,然后用map返回数组
const numArr = [...nums].map(function (num) {
// 直接从value里面拿的值
return parseInt(num.value);
});
//单价数组 单价数组保存在class=price中
const prices = document.querySelectorAll(".price");
// 处理单价 处理成数组//为什么使用textcontent 因为他在html中
const pricearr = [...prices].map(num => parseInt(num.textContent));
//金额数组
const amountArr = getAmount(numArr, pricearr);
console.log(amountArr);
// 总数量
document.querySelector(".total-num").textContent = zongshu(numArr);
// 金额
document.querySelectorAll(".amount").forEach((amount, index) => (amount.textContent = amountArr[index]));
// 总金额
document.querySelector(".total-amount").textContent = getTotalAmount(amountArr);
}
console.log(autoCalculate());
// 当购物车加载时触发
window.onload = autoCalculate;
//当数量更新时,触发自动计算
nums.forEach(num => (num.onchange = autoCalculate));
</script>
</html>
幻灯片部分,重新学习了onclick点击事件,已经定时器派发事件的使用,并且对函数的执行有了更加深入的了解,以及自定义dataset.index的深入了解
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<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>实战4: 轮播图</title>
<style>
/* ! 3. 轮播图 */
.slider {
max-width: 750px;
min-width: 320px;
margin: auto;
padding: 0 10px;
}
.slider .imgs {
/* 图片容器必须要有高度,否则下面图片不能正常显示 */
height: 150px;
}
.slider .imgs img {
/* 图片完全充满父级空间显示 */
height: 100%;
width: 100%;
/* 图片带有圆角 */
border-radius: 10px;
/* 默认图片全部隐藏,只有有active的图片才显示 */
display: none;
}
/* 默认显示第一张 */
.slider .imgs img.active {
display: block;
}
/* 轮播图按钮组 */
.slider .btns {
/* 按钮水平一排显示,用flex,且水平居中 */
display: flex;
place-content: center;
}
.slider .btns span {
/* 按钮宽高相同,确定显示成一个正圆 */
width: 8px;
height: 8px;
/* 加上红色背景和数字是为了布局时可以看到,一会更去掉 */
background-color: rgba(255, 255, 255, 0.4);
/* 50%可确保显示为正圆 */
border-radius: 50%;
/* 按钮上外边距负值,可将它上移,可移动到图片中下方 */
margin: -12px 3px 5px;
}
.slider .btns span.active {
background-color: #fff;
}
</style>
</head>
<body>
<div class="slider">
<!-- 图片容器 -->
<div class="imgs">
<!-- 轮播图默认从第一张开始显示 -->
<a href=""><img src="./images/banner1.jpg" alt="" data-index="1" class="active" /></a>
<a href=""><img src="./images/banner2.jpg" alt="" data-index="2" /></a>
<a href=""><img src="./images/banner3.png" alt="" data-index="3" /></a>
</div>
<!-- 切换按钮数量与图片数量必须一致 -->
<div class="btns">
<span data-index="1" class="active" onclick="setActive()"></span>
<span data-index="2" onclick="setActive()"></span>
<span data-index="3" onclick="setActive()"></span>
</div>
</div>
</body>
<script>
//获取全部图片及图片按钮
let imgs = document.querySelectorAll(".slider .imgs img")
console.log(imgs)
let spans = document.querySelectorAll(".slider .btns span")
console.log(spans)
// 设置激活按钮
function setActive() {
imgs.forEach(i => i.classList.remove("active"))
spans.forEach(i => i.classList.remove("active"))
// 触发者增加class active
event.target.classList.add("active");
// 图片已经设置了一个foreach循环删除active,下面遍历imgs,如果imgdataset.index===点击的spans触发者是同一个dataset.index
// 则img class增加active
imgs.forEach(function(img) {
if (img.dataset.index === event.target.dataset.index) {
img.classList.add("active")
}
});
}
// 设置定时器
setInterval(
function(arr) {
// 声明一个i,删除数组里面的第一项
let i = arr.shift(); ///括号 括号 不是中括号
// 派发事件i等于btns里面的索引,派发一个click点击事件
spans[i].dispatchEvent(new Event("click"));
// push尾部塞入 塞入是push() 括号 括号 不是中括号
arr.push(i);
},
2000,
Object.keys(spans)
);
</script>
</html>
下一篇: c++ switch用法