Correcting teacher:天蓬老师
Correction status:qualified
Teacher's comments:
对于图片过多的页面,为了加速页面加载速度,所以很多时候我们需要将页面内未出现在可视区域内的图片先不做加载, 等到滚动到可视区域后再去加载。当载入页面时,先把可视区域内的img标签的data-src属性值赋给src加载图片,然后监听滚动事件,把进入可视区域的图片src赋值加载。这样便实现了懒加载。<img src="images/temp.jpg" data-src="images/img-1.jpg" />
元素属性 | 说明 |
---|---|
clientHeight |
视口高度 |
scrollTop |
滚动距离 |
offsetTop |
图片距父级上偏移 |
当图片的offsetTop属性小于clientHeight+scrollTop属性之和时,即处于可视区域内。
进入可视区域内的图片按照设置延时进行img.src替换。
html文件代码:
<!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>
.container {
width: 400px;
display: grid;
gap: 10px;
grid-template-columns: repeat(4, 1fr);
}
.container img {
width: 100%;
border-radius: 20px;
}
</style>
</head>
<body>
<div class="container">
<img src="images2/temp.jpg" alt="" data-src="images2/img-1.jpg" />
<img src="images2/temp.jpg" alt="" data-src="images2/img-2.jpg" />
<img src="images2/temp.jpg" alt="" data-src="images2/img-3.jpg" />
<img src="images2/temp.jpg" alt="" data-src="images2/img-4.jpg" />
<img src="images2/temp.jpg" alt="" data-src="images2/img-5.jpg" />
<img src="images2/temp.jpg" alt="" data-src="images2/img-6.jpg" />
<img src="images2/temp.jpg" alt="" data-src="images2/img-7.jpg" />
<img src="images2/temp.jpg" alt="" data-src="images2/img-8.jpg" />
<img src="images2/temp.jpg" alt="" data-src="images2/img-9.jpg" />
<img src="images2/temp.jpg" alt="" data-src="images2/img-10.jpg" />
......
</div>
<script>
// 三个重点:视口高度clientHeight、滚动距离scrollTop、图片距父级上偏移offsetTop
// 获取图片元素集
const imgs = document.querySelectorAll(".container >img");
// console.log(imgs);
const clientHeight = document.documentElement.clientHeight;
// 监听窗口事件,初次载入时、滚动时
window.addEventListener("load", lazyLoad);
window.addEventListener("scroll", lazyLoad);
// 懒加载回调函数
function lazyLoad() {
let scrollTop = document.documentElement.scrollTop;
// 遍历所有图片,判断加载条件
imgs.forEach((img) => {
if (img.offsetTop < clientHeight + scrollTop) {
// 延时处理
setTimeout(() => {
img.src = img.dataset.src;
}, 600);
}
});
}
</script>
</body>
</html>
利用事件监听addEventListener()
、属性修改remove()/add()
、定时器setInterval()
、事件派发dispatchEvent()
等知识点实现轮播功能:
html文件代码:
<!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>
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}
a {
text-decoration: none;
}
/* 容器设置 */
.container {
width: 50em;
height: 20em;
margin: 1em auto;
position: relative; //定位元素,父级
}
/* 图片组 */
.container > .imgs img {
width: 100%;
height: 100%;
position: absolute;
left: 0;
top: 0;
display: none;
}
.container > .imgs img.active {
display: block;
}
/* 下方圆点按钮 */
.container > .btns {
position: absolute;
left: 0;
right: 0;
bottom: 0;
text-align: center;
}
.container > .btns a {
display: inline-block;
padding: 0.5em;
margin: 0 0.2em;
background-color: white;
border-radius: 50%;
}
.container > .btns a.active {
background-color: black;
}
/* 两侧翻页按钮 */
.container > .skip a {
position: absolute;
width: 2.5rem;
height: 5rem;
top: 7rem;
opacity: 0.3;
line-height: 4.6rem;
font-size: 2rem;
font-weight: lighter;
text-align: center;
background-color: white;
}
.container > .skip > .prev {
left: 0;
}
.container > .skip > .next {
right: 0;
}
</style>
</head>
<body>
<div class="container">
<!-- 轮播图片 -->
<nav class="imgs">
<a href="#"><img src="images/banner1.jpg" data-index="1" class="active" /></a>
<a href="#"><img src="images/banner2.jpg" data-index="2" /></a>
<a href="#"><img src="images/banner3.jpg" data-index="3" /></a>
<a href="#"><img src="images/banner4.jpg" data-index="4" /></a>
</nav>
<!-- 图片下方对应小按钮 -->
<nav class="btns"></nav>
<!-- 图片左右侧切换按钮 -->
<nav class="skip">
<a href="#" class="prev"><</a>
<a href="#" class="next">></a>
</nav>
</div>
<script>
// 获取元素
const imgs = document.querySelectorAll(".imgs img");
const btnG = document.querySelector(".btns");
// 根据图片数量创建下方圆点按钮
function autoCreatebtns(ele, imgLength) {
// 复用文档片断来简化编程
const frag = document.createDocumentFragment();
for (i = 0; i < imgLength; i++) {
const a = document.createElement("a");
a.href = "#";
a.dataset.index = i + 1;
if (i == 0) a.classList.add("active");
frag.append(a);
}
ele.append(frag);
}
autoCreatebtns(btnG, imgs.length);
// 1、 圆点按钮事件
const btns = document.querySelectorAll(".btns >*");
// console.log(btns);
// 拿到激活元素
function getActiveEle(ele) {
let activeEles = [...ele].filter((arr) => arr.classList.contains("active"));
// console.log(activeEles[0]);
return activeEles[0];
}
// 设置激活
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)));
// 2、两侧按钮事件
// 获取按钮元素集
const skip = document.querySelectorAll(".skip a");
// 拿到当前激活元素index
function getActiveIndx(ele) {
let activeEles = [...ele].filter((arr) => arr.classList.contains("active"));
return activeEles[0].dataset.index;
}
skip.forEach((item) => {
item.addEventListener("click", (ev) => {
let index = getActiveIndx(imgs) * 1;
switch (ev.target.className) {
case "prev":
// 左侧按钮图片激活index递减,到1循环
index = index == 1 ? imgs.length : index - 1;
setActiveEle(index);
break;
case "next":
//右侧按钮图片激活index递增,到length循环
index = index == imgs.length ? 1 : index + 1;
setActiveEle(index);
break;
}
});
});
// 3、自动循环轮播
// 轮播函数
function autoPlay(speed) {
// 创建定时器
timer = setInterval(() => {
const ev = new Event("click");
//给右侧按钮派发click事件
document.querySelector(".next").dispatchEvent(ev);
}, speed);
}
// 页面加载后开始轮播
window.onload = () => autoPlay(2000);
//鼠标移入时关闭轮播
document.querySelector(".container").onmouseover = () => clearInterval(timer);
//鼠标移出时启动轮播
document.querySelector(".container").onmouseout = () => autoPlay(2000);
//
</script>
</body>
</html>