1. 实例演示选项卡功能
<!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>实战: 选项卡效果</title>
</head>
<body>
<style>
.tabs {
width: 12em;
display: grid;
grid-template-columns: repeat(3, 1fr);
}
.tabs li {
list-style: none;
padding: 0.5em 1em;
}
.tabs li:hover {
cursor: pointer;
}
.content {
display: none;
}
.tabs .active {
background-color: cyan;
}
.content.active {
display: block;
}
</style>
<div class="box">
<!-- 选项卡 -->
<!-- 利用冒泡只需在ul设置事件 -->
<ul class="tabs" onclick="show()">
<!-- 每个列表加自定义属性,记录序号,点击后验证是点哪个列表,显示对应的内容 -->
<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="">12强赛-国足0-2完败日本 7战5分出线希望愈发渺茫</a></li>
<li><a href="">王燊超封堵时手触球送点 越南队7战0分提前出局</a></li>
<li><a href="">国足官方宣布郭田雨留洋 朱艺:维泽拉最高中锋仅1米</a></li>
<li><a href="">巴萨起诉前任主席巴托梅乌 经纪人表态登贝莱愿留队</a></li>
<li><a href="">李雯雯:回家过年因8点起床挨骂</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="">证监会坐实零跑汽车境外IPO传闻</a></li>
<li><a href="">常规电视剧剧集正片时长不能少于41分</a></li>
</ul>
<!-- 探索选项卡内容 -->
<ul class="content" data-index="3">
<li><a href="">这场大火已经燃烧了6000年</a></li>
<li><a href="">为什么电流会有嗡嗡响怪声音?</a></li>
<li><a href="">为什么说人类正输给超级细菌?</a></li>
<li><a href="">它一生可能只活5年,3.75年都在睡觉!</a></li>
<li><a href="">汤加火山爆发在地球另一端引发海啸</a></li>
</ul>
</div>
<script>
function show() {
// 1. 选项卡切换效果
// 使用event.currentTarget获取事件绑定元素,即ul,包含li
// 使用...转为数组,forEach方法遍历li元素,移除active样式
[...event.currentTarget.children].forEach((li) =>
li.classList.remove("active")
);
// 当前点击的标签加active样式
// 用event.target获取事件触发元素
event.target.classList.add("active");
// 2.内容显示效果
// 移除当前显示内容的active样式
// 方法同选项卡,用遍历
document
.querySelectorAll(".content")
.forEach((li) => li.classList.remove("active"));
// 显示自定义属性相同的内容
[...document.querySelectorAll(".content")]
.find((ul) => ul.dataset.index === event.target.dataset.index)
.classList.add("active");
}
</script>
</body>
</html>
2. 购物车
<!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>购物车</title>
</head>
<body>
<style>
.selectAll {
margin-top: 1em;
margin-left: 0.7em;
}
.selectAll *:hover {
cursor: pointer;
}
.shopingList {
padding: 0;
width: 35em;
background-color: lightskyblue;
}
.shopingList > li {
width: 35em;
display: grid;
grid-template-columns: 3.5em repeat(5, 5fr);
border-bottom: 1px solid rgb(12, 63, 105);
}
.shopingList > li:nth-of-type(1) {
color: #eee;
background-color: rgb(12, 63, 105);
}
li:last-of-type span:nth-of-type(1) {
text-align: center;
grid-column: 1 / span 5;
}
li:nth-of-type(n + 2):hover,
li input[type="checkbox"] {
cursor: pointer;
background-color: rgb(135, 194, 250);
}
h4,
span {
margin: 0.2em 0.6em;
}
h4 {
padding: 0.3em 0;
}
input[type="number"] {
width: 70%;
outline: none;
}
</style>
<div class="box">
<!-- 全选框 -->
<div class="selectAll">
<input
type="checkbox"
onchange="checkAll(),autoCount()"
name="check-all"
id="check-all"
/>
<label for="check-all">全选</label>
</div>
<ul class="shopingList">
<li>
<h4>选择</h4>
<h4>品名</h4>
<h4>数量</h4>
<h4>单位</h4>
<h4>单价(元)</h4>
<h4>金额(元)</h4>
</li>
<li>
<span><input type="checkbox" /> </span>
<span>土豆</span>
<span><input type="number" value="1" min="1" class="num" /></span>
<span>斤</span>
<span class="price">3.5</span>
<span class="amount">0</span>
</li>
<li>
<span><input type="checkbox" /> </span>
<span>土猪肉</span>
<span><input type="number" value="1" min="1" class="num" /></span>
<span>斤</span>
<span class="price">24</span>
<span class="amount">0</span>
</li>
<li>
<span><input type="checkbox" /> </span>
<span>啤酒</span>
<span><input type="number" value="1" min="1" class="num" /></span>
<span>瓶</span>
<span class="price">6.8</span>
<span class="amount">0</span>
</li>
<li>
<span>合计</span>
<span class="total-amount">2</span>
</li>
</ul>
</div>
</body>
<script>
// 1. 实现全选功能
function checkAll() {
// 获取触发事件的选择框状态;
let checkbox_status = event.target.checked;
// 定义数组,获取所有商品选择框元素
const checkbox_goods = document.querySelectorAll(
".shopingList input[type=checkbox]"
);
// 遍历商品选择框数组设为选择状态
checkbox_goods.forEach((i) => (i.checked = checkbox_status));
}
// 2. 根据每个商品选择状态来设置全选;
function checkbox() {
// 获取所有商品的选择框元素;
const checkbox_goods = document.querySelectorAll(
".shopingList input[type=checkbox]"
);
// 用数组的every方法判断所有选择框是否全是选中状态,返回true,定义变量存放
// 此处要注意,checkbox_goods不是数组,用...转为数组
let checkbox_goods_status = [...checkbox_goods].every(
(i) => i.checked === true
);
// 给全选框赋值
document.querySelector("#check-all").checked = checkbox_goods_status;
}
// 3. 商品的自动计算
// 单个商品的计算基于数量改变
// 合计计算基于所选择的商品
// 思路:先定义计算单个商品、计算合计两个函数
// 定义自动计算单个商品函数
// 定义自动计算合计函数
// 打开购物车时,判断勾选调用自动计算
// 商品数量变化时,判断勾选调用自动计算
// 勾选变化时调用自动计算
// 定义数组常量:记录商品数量元素。考虑后面要给每个元素加商品数量改变事件。
const input_nums = document.querySelectorAll(".num");
// 计算每个商品的金额函数:参数为数量数组,单价数组
function singleAmount(numArr, priceArr) {
// 用数组函数map遍历数量数组numArr计算金额
return numArr.map(
(goods_num, num_index) =>
parseFloat(goods_num) * parseFloat(priceArr[num_index])
);
}
// 计算合计金额的函数:参数为每个商品金额数组
function totalAmount(amountArr) {
// 用数组函数reduce遍历金额数组累加
return amountArr.reduce((total_value, amount) => total_value + amount);
}
// 自动计算函数
function autoCount() {
// 获取商品数量数组:数量元素转为数组,map遍历,再取每个元素的值
const goods_nums_Arr = [...input_nums].map(
(input_num) => input_num.value
);
// 获取商品单价元素
const prices_elements = document.querySelectorAll(".price");
// 商品单价数组:方法同上,取每个元素的文字内容,用parseFloat函数转为浮点数字
const goods_price_Arr = [...prices_elements].map((prices_element) =>
parseFloat(prices_element.textContent)
);
// 每个商品金额数组
const goods_single_amount_Arr = singleAmount(
goods_nums_Arr,
goods_price_Arr
);
// 获取每个商品全额元素,遍历每个元素,元素的文字内容设置为对应索引金额
document
.querySelectorAll(".amount")
.forEach(
(amount_element, index) =>
(amount_element.textContent = goods_single_amount_Arr[index])
);
// 获取选择框元素
const checked_elementArr = [
...document.querySelectorAll(".shopingList input[type=checkbox]"),
];
// 定义要统计合计的金额数组
let count_goods_single_amount_Arr = [];
// 定义合计元素变量
const total_amount_element = document.querySelector(".total-amount");
// 遍历选择框元素,勾选的,通过索引获取对应商品金额数组的数值组成新数组
checked_elementArr.forEach((element, index) => {
if (element.checked === true) {
count_goods_single_amount_Arr.push(goods_single_amount_Arr[index]);
}
});
// 计算并输出显示合计
document.querySelector(".total-amount").textContent =
count_goods_single_amount_Arr.length > 0
? totalAmount(count_goods_single_amount_Arr)
: 0;
}
// 加载购物车时调用自动计算
window.onload = autoCount;
// 商品数量变化时调用自动计算
// 要先给每个商品定义onchange事件
input_nums.forEach((element) => (element.onchange = autoCount));
// 监听选择框状态变化事件,调用自动计算。
[...document.querySelectorAll(".shopingList input[type=checkbox]")].forEach(
(element) =>
(element.onchange = () => {
checkbox();
autoCount();
})
);
</script>
</html>
3. 轮播图
<!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>轮播图</title>
</head>
<body>
<style>
.box {
min-width: 30%;
max-width: 60%;
margin: 30px auto;
padding: 0 10px;
}
.box .imgs {
/* height: 30%; */
}
.box .imgs img {
height: 100%;
width: 100%;
border-radius: 10px;
display: none;
}
.box .imgs img.active {
display: block;
}
.box .btns {
display: flex;
place-content: center;
}
.box .btns span {
width: 8px;
height: 8px;
background-color: rgba(255, 255, 255, 0.5);
border-radius: 50%;
margin: -12px 3px 5px;
}
.box .btns span.active {
background-color: rgb(1, 37, 90);
}
</style>
<div class="box">
<div class="imgs">
<a href="">
<img
src="https://img.alicdn.com/imgextra/i3/6000000002700/O1CN01IHv4w11Voe78qwWjW_!!6000000002700-0-octopus.jpg"
data-index="1"
class="active"
/>
</a>
<a href="">
<img
src="https://gtms03.alicdn.com/tps/i3/TB1gXd1JXXXXXapXpXXvKyzTVXX-520-280.jpg"
data-index="2"
/>
</a>
<a href="">
<img
src="https://gtms01.alicdn.com/tps/i1/TB1r4h8JXXXXXXoXXXXvKyzTVXX-520-280.jpg"
data-index="3"
/>
</a>
<a href="">
<img
src="https://gtms02.alicdn.com/tps/i2/TB10vPXKpXXXXacXXXXvKyzTVXX-520-280.jpg"
data-index="4"
/>
</a>
<a href="">
<img
src="https://img.alicdn.com/imgextra/i4/6000000001102/O1CN01HJ1Qxo1K0lCQcyutq_!!6000000001102-0-octopus.jpg"
data-index="5"
/>
</a>
</div>
<div class="btns">
<span data-index="1" class="active"></span>
<span data-index="2"></span>
<span data-index="3"></span>
<span data-index="4"></span>
<span data-index="5"></span>
</div>
</div>
<script>
// 一、点击按钮变换图片
// 1. 获取所有图片和按钮元素
const imgs = document.querySelectorAll(".box .imgs img");
const btns = document.querySelectorAll(".box .btns span");
// 给所有按钮添加事件
btns.forEach((btn) => (btn.onclick = setActive));
// 2. 定义按钮事件函数
function setActive() {
// 清空所有图片和按钮的激活样式
imgs.forEach((img) => img.classList.remove("active"));
btns.forEach((btn) => btn.classList.remove("active"));
// 根据点击按钮的索引属性确定显示的图片
// 先设置点击按钮为激活状态
event.target.classList.add("active");
// 查找相应索引图片,并显示
imgs.forEach((img) => {
if (img.dataset.index === event.target.dataset.index) {
img.classList.add("active");
}
});
}
// 二、定时播放
// 设置定时器,模拟定时点击按钮
// setInterval:三个参数,回调函数;定时时间;传给回调函数的参数
// 用定时器第三个参数给回调函数传按钮数组的索引,用object.keys方法可取数组的索引为数组
setInterval(
(btnArr) => {
// 原理:给回调函数传递按钮数组的索引,根据索引模拟点击对应的按钮
// 用数组方法shift拿出第1个值,数组中就没有了该值
let index = btnArr.shift();
// 根据索引模拟点击,用事件派发dispatchEvent
btns[index].dispatchEvent(new Event("click"));
// 把当前索引放到数组后面
btnArr.push(index);
},
2000,
Object.keys(btns)
);
</script>
</body>
</html>
4. 懒加载
<!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>懒加载</title>
<style>
h1 {
font-size: 5em;
}
img {
width: 100%;
}
</style>
</head>
<body>
<h1>第1张图片</h1>
<img
data-src="https://img.alicdn.com/imgextra/i3/6000000002700/O1CN01IHv4w11Voe78qwWjW_!!6000000002700-0-octopus.jpg"
/>
<h1>第2张图片</h1>
<img
data-src="https://gtms03.alicdn.com/tps/i3/TB1gXd1JXXXXXapXpXXvKyzTVXX-520-280.jpg"
/>
<h1>第3张图片</h1>
<img
data-src="https://gtms01.alicdn.com/tps/i1/TB1r4h8JXXXXXXoXXXXvKyzTVXX-520-280.jpg"
/>
<h1>第4张图片</h1>
<img
data-src="https://gtms02.alicdn.com/tps/i2/TB10vPXKpXXXXacXXXXvKyzTVXX-520-280.jpg"
/>
<h1>第5张图片</h1>
<img
data-src="https://img.alicdn.com/imgextra/i4/6000000001102/O1CN01HJ1Qxo1K0lCQcyutq_!!6000000001102-0-octopus.jpg"
/>
</body>
<script>
// 图片位置在视口中时才加载显示
// 原理:
// 把图片链接放在自定义属性data-src中
// 用getBoundingClientRect()方法返回元素的位置和大小
// 判断图片顶部位置是否小于视口高度window.innerHeight,小则将src属性设为data-src值
// 定义加载函数
function load() {
// 取得所有图片转换为元素数组,遍历并判断位置,可用document.images对象
[...document.images].forEach((img) => {
if (img.getBoundingClientRect().top < window.innerHeight) {
img.src = img.dataset.src;
}
});
}
// 定义页面加载事件
window.onload = load;
// 定义窗口滚动事件
window.onscroll = load;
</script>
</html>