1、双色球
<!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 {
display: grid;
grid-template-columns: repeat(auto-fill, 30px);
grid-auto-rows: 30px;
gap: 5px;
}
.box > div {
border-radius: 50%;
display: grid;
place-items: center;
background-color: red;
color: white;
box-shadow: 2px 2px 2px #666;
}
.box > div:last-of-type {
background-color: blue;
}
</style>
</head>
<body>
<div class="box"></div>
<button onclick="refresh()" style="margin-top: 10px">抽奖</button>
<script>
function refresh() {
// 红球: 1-33=>6,不重复,排序
// 蓝球: 1-16=>1, 可以和红球重复
// 思路:
// 1. 先取红球, 放在一个中奖号数组中, 排序
// 2. 然后把蓝球追加到中奖数组中
// 3. 最后还要马中奖数组渲染到页面: dom
// 临时数组: 放红球
let arr = [];
// 全部中奖数组,最后应该有7个数,6个红球,1个蓝球
let res = [];
// 1. 生成1-33个红球
for (let i = 1; i <= 33; i++) {
arr.push(i);
}
console.log(arr);
// 2. 从33个红球中取出6个
for (let i = 0; i < 6; i++) {
// arr的下标取值范围: [0-32]
// 问题: 如何生成0-32这样的整数索引,用它来获取数组中的数据
// Math.random(): 0-1之间的随机小数
// console.log(Math.random());
// 0-33之间的小数,但永远不会到33这个数
// 0.0123, 32.999999, 向下取整
// 0.0123 => 0
// 32.9999999 => 32
// console.log(Math.random() * 33);
// console.log(Math.random() * arr.length);
// console.log(Math.floor(Math.random() * arr.length));
// 索引是唯一的,为什么重复了
// 索引不会重复,但是对应的值会重复
// [1,2,3,2]
// 0=>1,1=>2, 2=>3, 3=>2
// 应该每取一个就从原始数组中删除一个
let index = Math.floor(Math.random() * arr.length);
// console.log(Math.ceil(1.000001));
res.push(arr[index]);
arr.splice(index, 1);
}
// 排序
res.sort((a, b) => a - b);
console.log(res);
// 3. 生成一个蓝球, 并追加到中奖数组中
// 必须是: 1-16之间,并包括 1, 16
let blue = Math.floor(Math.random() * 16) + 1;
console.log(blue);
res.push(blue);
console.log(res);
// 4. 将中奖号码显示到页面中
const box = document.querySelector(".box");
let box_content = box.children.length;
console.log(box_content);
console.log("不太明白这里的判断作用");
if (box_content !== 0) {
box.innerHTML = "";
}
res.forEach((item) => {
const ball = document.createElement("div");
ball.textContent = item;
box.append(ball);
});
}
window.onload = refresh;
</script>
</body>
</html>
2、选项卡
<!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: 28em;
display: grid;
grid-template-columns: 3em 1fr;
}
.box ul {
margin: 0;
padding: 0;
}
.box li {
list-style: none;
/* height: 2em; */
}
.box li a {
text-decoration: none;
}
.box li:hover {
cursor: pointer;
}
.box .content {
background-color: lightgreen;
display: none;
place-self: center start;
}
.box .content.active {
display: block;
}
.box .menu li.active {
background-color: lightgreen;
}
</style>
</head>
<body>
<div class="box">
<!-- 标签 -->
<!-- 子元素(li点击)上的点击事件会冒泡到父元素(ul),利用这个特点,只需要给父元素添加点击事件即可 -->
<ul class="menu" onclick="show()">
<!-- 默认显示的标签和内容添加:class="active" -->
<!-- 使用自定义属性data-index使标签和内容进行绑定 -->
<li data-index="1" class="active">本市</li>
<li data-index="2">本省</li>
<li data-index="3">全国</li>
</ul>
<!-- 内容 -->
<ul class="content active" data-index="1">
<li><a href="">本市新闻本市新闻本市新闻本市新闻本市新闻</a></li>
<li><a href="">本市新闻本市新闻本市新闻本市新闻本市新闻</a></li>
<li><a href="">本市新闻本市新闻本市新闻本市新闻本市新闻</a></li>
<li><a href="">本市新闻本市新闻本市新闻本市新闻本市新闻</a></li>
<li><a href="">本市新闻本市新闻本市新闻本市新闻本市新闻</a></li>
</ul>
<ul class="content" data-index="2">
<li><a href="">本省新闻本省新闻本省新闻</a></li>
<li><a href="">本省新闻本省新闻本省新闻</a></li>
<li><a href="">本省新闻本省新闻本省新闻</a></li>
<li><a href="">本省新闻本省新闻本省新闻</a></li>
<li><a href="">本省新闻本省新闻本省新闻</a></li>
</ul>
<ul class="content" data-index="3">
<li><a href="">全国新闻全国新闻全国新闻全国新闻全国</a></li>
<li><a href="">全国新闻全国新闻全国新闻</a></li>
<li><a href="">全国新闻全国新闻全国新闻</a></li>
<li><a href="">全国新闻全国新闻全国新闻</a></li>
<li><a href="">全国新闻全国新闻全国新闻</a></li>
</ul>
</div>
<script>
function show() {
// console.log("hello");
// 事件绑定者ul
// console.log(event.currentTarget);
// 事件触发者:事件主体li
// console.log(event.target);
const ul = event.currentTarget;
const li = event.target;
// 标签的切换
// 1.将原来的高亮标签"active"去掉
[...ul.children].forEach((li) => li.classList.remove("active"));
// 2.新点击的ul下的li添加属性:class="active"
li.classList.add("active");
// 内容区处理
// 根据标签的data-index进行查询,获取与标签对应的内容切换
const content = document.querySelectorAll(".content");
// document.querySelectorAll()返回的是NodeList对象,上面已定义了forEach
// console.log(content);
// 1.将原来的高亮标签"active"去掉
content.forEach((li) => li.classList.remove("active"));
// 2.把当前点击的标签对应的content显示出来
// 获取到data-index对应的值的内容
// console.log([...content].find((ul) => ul.dataset.index === li.dataset.index));
// 添加属性:class="active"
[...content].find((ul) => ul.dataset.index === li.dataset.index).classList.add("active");
}
</script>
</body>
</html>
3、购物车(实现动态勾选商品计算价格)
<!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">
<!-- checkAll(): 当全选按钮的状态发生变化化,触发该事件 change -->
<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" max="5" 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>
<script>
// 1.全选功能
function checkAll() {
// 1.全选按钮状态
// let status = document.querySelector(".check-all").checked;
// 事件主体引用
let status = event.target.checked;
// console.log(status);
// 2.动态设置所有商品的状态
// document.querySelectorAll('.list li input[type="checkbox"]');
let items = document.querySelectorAll('.list li input[type="checkbox"]');
// 遍历商品input,修改状态 checked
items.forEach((item) => (item.checked = status));
}
// 2.根据用户选择动态设置:取消其中一个时,全选取消,反之也是
function checkItems() {
// alert(1);
// 1.拿到全部商品
let items = document.querySelectorAll(".list li input[type='checkbox']");
// 2.判断状态,只有全部选,才设置全选true,Array.every
let status = [...items].every((item) => item.checked === true);
// 状态变化
document.querySelector(".check-all").checked = status;
// 更新
autoCalculate();
console.log(status);
// 3.将这个新状态设置到全选按钮上
document.querySelector(".check-all").checked = status;
}
// 商品的自动计算
// 所有的计算时基于商品数量的变化
// 计算选中的商品总数量
const nums = document.querySelectorAll(".num");
// 商品是否被选中
function selectedItem(numArr) {
let items = document.querySelectorAll(".list li input[type='checkbox']");
return numArr.map((num, index) => {
if (items[index].checked === false) {
return (num = 0);
} else {
return num;
}
});
}
// 计算商品总数量
// console.log(nums);
// 查看商品数量
// nums.forEach((item) => console.log(item.value));
// 1.求和计算商品总数量
function getTotalNum(numArr) {
numArr = selectedItem(numArr);
return numArr.reduce((acc, cur) => acc + cur);
}
// console.log(getTotalNum([1, 2, 3]));
// 2.计算每个商品的金额
function getAmount(numArr, priceArr) {
// 金额 = 商品单价 * 数量
return numArr.map((num, index) => num * priceArr[index]);
}
// 3.计算总金额
function getTotalAmount(amountArr) {
amountArr = selectedItem(amountArr);
return amountArr.reduce((acc, cur) => acc + cur);
}
// 4.自动计算
function autoCalculate() {
// 商品数量数组
// parseInt()和Number():字符串转换为数字
const numArr = [...nums].map((num) => parseInt(num.value));
console.log(numArr);
//商品单价数组
const prices = document.querySelectorAll(".price");
const priceArr = [...prices].map((price) => parseInt(price.textContent));
console.log(priceArr);
// 金额数组
const amountArr = getAmount(numArr, priceArr);
console.log(amountArr);
// 计算商品总数量
console.log(getTotalNum(numArr));
// 渲染到显示页面
document.querySelector(".total-num").textContent = getTotalNum(numArr);
// 渲染总金额到页面中显示
document.querySelector(".total-amount").textContent = getTotalAmount(amountArr);
// 渲染每个商品的计算金额到页面中显示
document
.querySelectorAll(".amount")
.forEach((amount, index) => (amount.textContent = amountArr[index]));
}
// console.log(getAmount([12, 2, 3], [100, 200, 300]));
// autoCalculate();
// 当页面加载的时候自动计算
// window.onload = function () {
// autoCalculate();
// };
// 简化
window.onload = autoCalculate();
// 当数量更新时,自动计算其他数据
[...nums].forEach((num) => (num.onchange = autoCalculate));
</script>
</body>
</html>