选项卡
//css样式
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
a {
text-decoration: none;
color: #333;
}
ul li {
list-style: none;
}
.con {
width: 20em;
box-shadow: 0 0 3px #ccc;
margin: 2em;
}
.con .tab {
display: grid;
grid-template-columns: repeat(3, 1fr);
text-align: center;
background-color: #ccc;
}
.con .tab li {
padding: 0.5em 0;
cursor: pointer;
}
.con .active {
background-color: #fff;
}
.con .item {
padding: 0.5em;
}
.con .item li {
padding: 0.2em 0;
}
.item {
padding: 20px;
display: none;
}
.item.active {
display: block;
}
</style>
//html代码
<div class="con">
<ul class="tab">
<li class="active" data-index="1">第一个</li>
<li data-index="2">第二个</li>
<li data-index="3">第三个</li>
</ul>
<ul data-index="1" class="item active">
<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>
<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 data-index="2" class="item">
<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>
<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 data-index="3" class="item">
<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>
<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>
//js代码
<script>
const tab = document.querySelector(".con .tab");
const items = document.querySelectorAll(".con .item");
tab.onmouseover = (ev) => {
[...tab.children].forEach((item) => item.classList.remove("active"));
console.log([Array.from(tab.children)]);
ev.target.classList.add("active");
items.forEach((item) => item.classList.remove("active"));
[...items].filter((item) => item.dataset.index === ev.target.dataset.index)[0].classList.add("active");
};
</script>
图片懒加载
//html代码
<ul class="imgs">
<img src="images/temp.jpg" alt="" data-src="images/img-1.jpg" />
<img src="images/temp.jpg" alt="" data-src="images/img-2.jpg" />
<img src="images/temp.jpg" alt="" data-src="images/img-3.jpg" />
<img src="images/temp.jpg" alt="" data-src="images/img-4.jpg" />
<img src="images/temp.jpg" alt="" data-src="images/img-5.jpg" />
<img src="images/temp.jpg" alt="" data-src="images/img-6.jpg" />
<img src="images/temp.jpg" alt="" data-src="images/img-7.jpg" />
<img src="images/temp.jpg" alt="" data-src="images/img-8.jpg" />
<img src="images/temp.jpg" alt="" data-src="images/img-9.jpg" />
<img src="images/temp.jpg" alt="" data-src="images/img-10.jpg" />
<img src="images/temp.jpg" alt="" data-src="images/img-11.jpg" />
<img src="images/temp.jpg" alt="" data-src="images/img-12.jpg" />
<img src="images/temp.jpg" alt="" data-src="images/img-13.jpg" />
<img src="images/temp.jpg" alt="" data-src="images/img-14.jpg" />
<img src="images/temp.jpg" alt="" data-src="images/img-15.jpg" />
<img src="images/temp.jpg" alt="" data-src="images/img-16.jpg" />
<img src="images/temp.jpg" alt="" data-src="images/img-17.jpg" />
</ul>
//js代码
<script>
//获取图片列表
const imgs = document.querySelectorAll(".imgs img");
//获取当前视口高度
const clientHeight = document.documentElement.clientHeight;
window.addEventListener("scroll", layzyload);
window.addEventListener("load", layzyload);
function layzyload() {
//获取滚动高度
let scrollTop = document.documentElement.scrollTop;
//遍历当前图片是否到了可视区 图片到顶部的高度小于视口+滚动高度,即认为图片进入可视区
imgs.forEach((img) => {
if (img.offsetTop < scrollTop + clientHeight) {
setTimeout(() => (img.src = img.dataset.src), 500);
}
});
}
</script>
轮播图
//html代码
<div class="container">
<!-- 1. 图片组 -->
<nav class="imgs">
<a href="#"
><img src="banner/banner1.jpg" alt="" data-index="1" class="active"
/></a>
<a href="#"><img src="banner/banner2.jpg" alt="" data-index="2" /></a>
<a href="#"><img src="banner/banner3.jpg" alt="" data-index="3" /></a>
<a href="#"><img src="banner/banner4.jpg" alt="" data-index="4" /></a>
</nav>
<!-- 2. 与图片组对应的按钮组(一个个独立的,数量与图片数量是相同的) -->
<nav class="btns">
<!-- 这些小按钮应该是js根据图片数量动态来创建 -->
</nav>
<!-- 3. 翻页按钮(只有二个,分别在左右) -->
<nav class="skip">
<!-- <: 实体符号 -->
<a href="#" class="prev"><</a>
<a href="#" class="next">></a>
</nav>
</div>
//JS代码
<script>
// 获取相关的元素对象
// 图片组
const imgs = document.querySelectorAll(".container > .imgs img");
// 按钮组
const btnGroup = document.querySelector(" .container > .btns");
// 翻页按钮
const skip = document.querySelector(" .container > .skip");
// 自动生成按钮组,数量与图片数量一致
function autoCreateBtns(ele, imgLength) {
// 使用文档片断
const frag = document.createDocumentFragment();
for (let i = 0; i < imgLength; i++) {
const a = document.createElement("a");
// #: 防止默认行为,更加规范用 ev.preventDefault();
a.href = "#";
// 自定义数据属性
a.dataset.index = i + 1;
// 为第一个按钮添加高亮,这是默认的
if (i === 0) a.classList.add("active");
frag.appendChild(a);
}
ele.appendChild(frag);
}
// 调用该函数自动生成与图片一一对应的小按钮
autoCreateBtns(btnGroup, imgs.length);
// 获取到刚生成的按钮组中所有按钮
const btns = document.querySelectorAll(" .container > .btns > *");
// 下面声明2个公共函数
// 1. 获取激活的元素
function getActiveEle(eles) {
let activities = Array.from(eles).filter(img =>
img.classList.contains("active")
);
return activities.shift();
}
// 2. 设置激活的元素
function setActiveEle(btnIndex) {
// 同时遍历所有图片与按钮
[imgs, btns].forEach(arr => {
// 取消当前激活元素的状态
getActiveEle(arr).classList.remove("active");
// 根据当前用户点击的按钮索引,重置应该激活的元素
arr.forEach(item => {
if (item.dataset.index === btnIndex) {
item.classList.add("active");
}
});
});
}
// 为每一个独立的小按钮添加事件,不要使用事件代理
btns.forEach(btn =>
btn.addEventListener(
"click",
ev => setActiveEle(ev.target.dataset.index),
false
)
);
// 作业1: 为每个翻页按钮添加事件完成图片翻页(兄弟节点的处理)
skip.addEventListener("click", skipImg, false);
// 单独写一个事件监听器,为后面的事件自动派发做准备
skip.children[0].addEventListener("click", skipImg, false);
// 将前后翻页,使用一个回调统一处理
function skipImg(ev) {
// 当前激活的图片,实际上这里用不到它,而应该用它的父级<a>来判断是否存在兄弟节点
let currentImg = getActiveEle(imgs);
// 当前图片组父元素,注意<img>父级是<a>,<a>的父级才是需要的父节点
let parentEle = currentImg.parentElement.parentElement;
// 当前元素的前一个兄弟节点:previousElementSibling;
let prevEle = currentImg.parentElement.previousElementSibling;
// 当前元素的下一个兄弟节点:nextElementSibling;
let nextEle = currentImg.parentElement.nextElementSibling;
// 第一张图片, firstElementChild第一个子元素
let firstImg = parentEle.firstElementChild.firstElementChild;
// 最后一张图片, firstElementChild, 最后一个子元素
let lastImg = parentEle.lastElementChild.firstElementChild;
let activeImg = currentImg;
// 向前翻页
if (ev.target.classList.contains("prev")) {
// 如果存在前一张图片,就使用它,否则就使用最后一张图片来更新它,形成循环显示的效果
let activeImg =
prevEle !== null ? prevEle.firstElementChild : lastImg;
// 使用激活元素来同步更新图片与按钮
setActiveEle(activeImg.dataset.index);
}
// 向后翻页
if (ev.target.classList.contains("next")) {
// 如果不存在下一张图片,就用第一张图片更新它
let activeImg =
nextEle !== null ? nextEle.firstElementChild : firstImg;
setActiveEle(activeImg.dataset.index);
}
}
// 作业2: 图片每隔2秒自动播放(定时器,事件自动派发)
let timer = null;
const slider = document.querySelector(".container");
slider.addEventListener("mouseout", startTimer, false);
slider.addEventListener("mouseover", clearTimer, false);
// 启动定时器
function startTimer() {
// 创建自定义事件对象
const clickEvent = new Event("click");
timer = setInterval(
() => skip.children[0].dispatchEvent(clickEvent),
2000
);
}
// 清除定时器
function clearTimer() {
clearInterval(timer);
}
</script>