JavaScript三大原则
组件封装
用原生JS实现轮播图
需求:
- 点击左按钮,当前这一张消失,出现上一张。
- 点击右按钮,当前这一张消失,出现下一张。
- 点击焦点按钮,当前这一张消失,出现某一张。
如下图所示
实现要求:
- 图片循环播放:轮番图需要能够循环显示出一组图片,让用户能够连续浏览不同的图片。
- 自动播放和暂停:当用户不进行任何操作时,轮番图应该自动播放图片,但当用户鼠标悬停在图片上时,轮番图应该暂停播放。
- 图片标记和切换按钮:轮番图需要显示当前展示的是第几张图片,并提供切换按钮供用户手动切换图片。
- 响应式设计:轮番图需要适应不同设备的屏幕尺寸,确保在不同的设备上都有良好的显示效果。
- 动画效果:轮番图可以用动画效果实现图片的切换,例如淡入淡出、滑动等效果,用于提升用户体验。
代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
* { margin: 0; padding: 0; }
ul, ol, li { list-style: none;}
img { width: 100%; height: 100%;display: block; }
.banner { width: 100%; height:500px;position:relative;
margin: 50px 0;}
.banner > ul { width: 100%;height: 100%;position: relative;}
.banner > ul > li {width: 100%; height: 100%;
position: absolute;left: 0;top: 0;opacity: 0;
transition: opacity .5s linear;}
.banner > ul > li.active { opacity: 1;}
.banner > ol { width: 200px;height: 30px;
position: absolute;left: 30px;bottom: 30px;
background-color: rgba(0, 0, 0, .5);display: flex;
justify-content: space-around;align-items: center;
border-radius: 15px;}
.banner > ol > li { width: 20px;height: 20px;
background-color: #fff;border-radius: 50%;
cursor: pointer;}
.banner > ol > li.active {background-color: orange;}
.banner > div {width: 40px;height: 60px;
position: absolute;top: 50%;transform: translateY(-50%);
background-color: rgba(0, 0, 0, .5);display: flex;
justify-content: center; align-items: center;
font-size: 30px; color: #fff;cursor: pointer;}
.banner > div.left {left: 0;}
.banner > div.right {right: 0;}
</style>
</head>
<body>
<div class="banner">
<!-- 图片区域 -->
<ul class="imgBox">
<li class="active">
<img src="img/01.png" alt="图片1"></li>
<li><img src="img/02.png" alt="图片2"></li>
<li><img src="img/03.jpg" alt="图片3"></li>
<li><img src="img/04.jpg" alt="图片4"></li>
</ul>
<!-- 焦点区域 -->
<ol>
<li data-i="0" data-name="point" class="active"></li>
<li data-i="1" data-name="point"></li>
<li data-i="2" data-name="point"></li>
<li data-i="3" data-name="point"></li>
</ol>
<!-- 左右切换按钮 -->
<div class="left"><</div>
<div class="right">></div>
</div>
<script>
// 获取到所有承载图片的 li 和所有承载焦点的 li
var imgs = document.querySelectorAll('ul > li')
var points = document.querySelectorAll('ol > li')
var banner = document.querySelector('.banner')</script>
// 准备一个变量, 表示当前是第几张, 默认是 0, 因为默认显示的是索引第 0 张
var index = 0
// 书写一个切换一张的函数
// 约定:
// 参数为 true, 我们切换下一张
// 参数为 false, 我们切换上一张
// 参数为 数字, 我们切换到指定索引的那一张
function changeOne(type) {
// 1. 让当前这一张消失
imgs[index].className = ''
points[index].className = ''
// 2. 根据 type 传递来的参数, 来切换 index 的值
if (type === true) {
index++
} else if (type === false) {
index--
} else {
index = type
}
// 判定一下 index 的边界值
if (index >= imgs.length) {
index = 0
}
if (index < 0) {
index = imgs.length - 1
}
// 3. 让改变后的这一张显示出来
imgs[index].className = 'active'
points[index].className = 'active'
}
// 给 轮播图区域 盒子绑定点击事件
banner.onclick = function (e) {
// 判断点击的是左按钮
if (e.target.className === 'left') {
console.log('点击的是左按钮')
// 切换上一张, 调用 changeOne 方法传递参数为 false
changeOne(false)
}
// 判断点击的是右按钮
if (e.target.className === 'right') {
console.log('点击的是右按钮')
// 切换下一张, 调用 changeOne 方法传递参数为 true
changeOne(true)
}
// 判断点击的是焦点盒子
if (e.target.dataset.name === 'point') {
console.log('点击的是焦点盒子')
// 拿到自己身上记录的索引
var i = e.target.dataset.i - 0
// 切换某一张, 调用 changeOne 方法传递参数为要切换的索引
changeOne(i)
}
}
// 自动切换功能
setInterval(function () {
// 切换到下一张
changeOne(true)
}, 5000)
</style>
总结
这是一个简单的图片轮播器,具有切换、自动播放和手动切换功能。
- 在上方
<style>标签中,存放着对各个元素的样式定义。 - 在
<div class="banner">内部,有一个图片区域(<ul class="imgBox">),其中包含了一系列图片(<li>)。还存在一个焦点区域(<ol>),其中的列表项(<li>)对应每张图片。当前显示的列表项和图片都具有active类名。另外,左右切换按钮(<div class="left">和<div class="right">)用于手动切换图片。 - 在
<script>标签中,首先通过document.querySelectorAll方法获取到图片和焦点的元素。其中imgs为图片元素的集合,points为焦点元素的集合,banner为轮播图区域的元素。变量index表示当前显示的是第几张图片,初始值为0。changeOne函数用于切换图片。可以传入true表示切换至下一张,false表示切换至上一张,或者传入指定的索引来切换图片。 - 在
banner.onclick中绑定点击事件,通过判断点击的是左/右按钮还是焦点盒子来触发切换事件。setInterval函数用于自动切换图片,每隔5秒调用一次changeOne(true)来切换至下一张图片。
JavaScript部分首先获取到图片元素、焦点元素和banner容器的引用。然后定义了一个changeOne函数来完成切换图片的功能,根据传入的参数来切换图片,并且更新对应的焦点。最后,在banner容器上绑定点击事件,根据点击的目标元素来判断是左切换按钮、右切换按钮还是焦点盒子的点击,并调用changeOne函数来进行相应的切换。同时,还设定了定时器,每隔5秒自动切换到下一张图片。
过程抽象
为了满足不同事件处理中的“只执行一次”的需求,我们可以将该功能进行抽象。这个过程被称为过程抽象。通过将这个功能定义为一个单独的函数或方法,我们可以在不同的事件处理中重复使用。
- 用来处理局部细节控制的一些方法。
- 函数式编程思想的基础应用。
操作次数限制:
-
一些异步交互;
-
一次性的HTTP请求
const list = document . querySelector( 'ul' ); const buttons = list. querySelectorAll( 'button' );buttons. forEach( (button) => { button. addEventListener( 'click' , (evt) => { consttarget = evt. target ; target . parentNode. className = ' completed' ;setTimeout(( ) => { list. removeChild( target . parentNode );},2000 ); }); });
-
querySelector('ul'):通过选择器获取页面中第一个ul元素(文档中的一个元素)。这是一次异步操作,因为需要等待DOM加载完成才能执行。 -
querySelectorAll('按钮'):通过选择器获取页面中所有的button元素(文档中的多个元素)。这也是一次异步操作,需要等待DOM加载完成。 -
按钮.forEach():对按钮数组进行遍历操作,为每个按钮元素添加事件监听器。这是一次同步操作,因为在代码执行期间完成。 -
按钮.addEventListener('click', () => {...}):为每个按钮元素添加点击事件监听器。这是一次同步操作,因为在代码执行期间完成。 - 事件监听器内的代码逻辑包括:
a.获取点击事件的目标元素const target = evt.target;
b. 修改目标元素的父节点的类名为"已完成"target.parentNode.className = 'finished';
c. 设置一个延迟定时器,在两秒后执行
d. 在定时器回调函数中,移除目标元素的父节点列表.removeChild(target.parentNode);
以上涉及到的操作次数限制主要取决于页面中ul元素和button元素的数量。异步操作需要等待DOM加载完成,而同步操作提供了即时的执行。注意,HTTP请求并没有在提供的代码中体现,可能存在于其他部分的代码中。