面向对象 完成技巧
定义变量 ---> 改成属性 this.xxx = yyyy 书写在构造函数的函数体内
定义函数 ---> 改成方法 直接书写在构造函数的原型对象内
方法内的变量:
1) 如果需要在别的函数内使用, 那么将这个变量直接写在 构造函数的函数体内 (以前的解决方案是写到全局)
2) 如果只需要在当前函数内使用, 那么直接将这个变量定义在当前函数内
1. 轮播图
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>Document</title>
<style>
* {
padding: 0;
margin: 0;
}
.banner {
width: 600px;
height: 400px;
border: 5px solid black;
margin: 200px auto;
/* overflow: hidden; */
position: relative;
}
.banner .img_box {
width: 100%;
height: 100%;
list-style: none;
display: flex;
position: absolute;
left: 0px;
}
.banner .img_box li {
width: 600px;
height: 100%;
font-size: 50px;
text-align: center;
line-height: 400px;
display: none;
}
.banner .img_box .active {
display: block;
}
.banner .focus {
width: 200px;
height: 30px;
background-color: white;
position: absolute;
left: 50%;
transform: translateX(-50%);
bottom: 30px;
border-radius: 20px;
display: flex;
justify-content: space-evenly;
align-items: center;
list-style: none;
}
.banner .focus li {
width: 20px;
height: 20px;
border-radius: 50%;
background-color: rosybrown;
cursor: pointer;
}
.banner .focus .active {
background-color: red;
}
.left,
.right {
position: absolute;
transform: translateY(-50%);
font-size: 50px;
color: white;
top: 50%;
cursor: pointer;
}
.left {
left: 30px;
}
.right {
right: 30px;
}
</style>
</head>
<body>
<div class="banner" id="box1">
<!-- 放置所有轮播图的盒子 -->
<ul class="img_box">
<li class="active" style="background-color: burlywood;">1</li>
<li style="background-color: royalblue;">2</li>
<li style="background-color: greenyellow;">3</li>
<li style="background-color: pink;">4</li>
<li style="background-color: rgb(201, 255, 192);">5</li>
</ul>
<!-- 放置焦点的盒子 -->
<ol class="focus">
<!-- <li class="active"></li>
<li></li>
<li></li>
<li></li>
<li></li> -->
</ol>
<!-- 左右按钮 -->
<div class="left"><</div>
<div class="right">></div>
</div>
<div class="banner" id="box2">
<!-- 放置所有轮播图的盒子 -->
<ul class="img_box">
<li class="active" style="background-color: burlywood;">1</li>
<li style="background-color: royalblue;">2</li>
<li style="background-color: greenyellow;">3</li>
<li style="background-color: pink;">4</li>
<li style="background-color: rgb(201, 255, 192);">5</li>
</ul>
<!-- 放置焦点的盒子 -->
<ol class="focus">
<!-- <li class="active"></li>
<li></li>
<li></li>
<li></li>
<li></li> -->
</ol>
<!-- 左右按钮 -->
<div class="left"><</div>
<div class="right">></div>
</div>
<script src="./index.js"></script>
<script>
const b1 = new Banner('#box1')
// b1.setFocus()
// b1.autoPlay()
// b1.mouseMove()
// b1.clickBtn()
new Banner('#box2')
</script>
</body>
</html>
js文件
/**
* 面向过程
*
* 1. 分析
* => 属性 (变量)
* + banner -> 轮播图可视区域盒子
* + imgBox -> 存放图片的 ul
* + index -> 表明当前展示的第几张图片
* + timer -> 定时器 ID
* => 方法
* + copyEle -> 处理假图
* + setFocus -> 设置焦点
* + autoplay -> 自动轮播
*
* 面向对象 完成技巧
* 定义变量 ---> 改成属性 this.xxx = yyyy 书写在构造函数的函数体内
* 定义函数 ---> 改成方法 直接书写在构造函数的原型对象内
*
* 方法内的变量: 如果需要在别的函数内使用, 那么将这个变量直接写在 构造函数的函数体内 (以前的解决方案是写到全局)
* 如果只需要在当前函数内使用, 那么直接将这个变量定义在当前函数内
*/
// function Banner () {}
class Banner {
// 构造器, 类似于 构造函数的函数体
constructor(ele) {
this.ele = document.querySelector(ele);
this.imgBox = this.ele.querySelector(".img_box");
this.focus = this.ele.querySelector(".focus");
this.index = 0; // 这里使用下标表示, 如果值为0, 代表展示第一张图
this.timer = 0; // 存储定时器 ID
// this.setFocus();
// this.autoPlay();
// this.mouseMove();
// this.clickBtn();
this.init();
}
// 以下位置书写原型
init() {
this.setFocus();
this.autoPlay();
this.mouseMove();
this.clickBtn();
}
// 1. 根据图片数量 设置焦点
setFocus() {
// 1.1 获取图片数量
let liNum = this.imgBox.children.length;
// 1.2 根据图片数量生成焦点
for (let i = 0; i < liNum; i++) {
// 1.2.1 创建一个 li 标签
const newLi = document.createElement("li");
// 将下标绑定在 标签上
newLi.dataset.id = i;
// 给 每一个 li 添加一个 类名
newLi.classList.add("focus_item");
// 1.2.2 添加类名
i === 0 && newLi.classList.add("active");
// 1.2.3 插入到 DOM 视图中
this.focus.appendChild(newLi);
}
}
// 1.5 重新封装一个类似 move 函数的方法
cut(type) {
/**
* 1. 点击切换到下一张 (自动切换到下一张)
* 2. 点击切换到上一张
* 3. 点击某焦点切换到某一张
*
*
* 我对我自己有一个约定
* 调用 cut 函数的时候 传递三个不同的参数, 让代码根据参数的不同 做对应的事
*
* 如果传递的是 true 下一张
* 传递的是 false 上一张
* 传递的是数字 切换到某一张
*/
// 1.5.1 函数开始执行, 在这里 我们的 this.index 表示的是当前界面中, 哪一个 li 具有类名, 所以可以直接找到它 取消类名
this.imgBox.children[this.index].classList.remove("active");
this.focus.children[this.index].classList.remove("active");
// 1.5.2 根据参数确定一会要展示那一张图
if (type === true) {
// 切换到下一张
this.index++;
} else if (type === false) {
// 切换到上一张
this.index--;
} else {
// 当前分支执行 切换到某一张, 具体是那一张需要根据 参数 type 的实际值来确定
this.index = type;
}
// 边界限制, 如果滚动到最后一张, 那么下一次应该展示的是 下标 0 的图片
if (this.index >= this.imgBox.children.length) {
this.index = 0;
}
// 边界限制, 如果在第一张, 并且需要滚动到上一张, 那么实际应该展示的是最后一张
if (this.index < 0) {
this.index = this.imgBox.children.length - 1;
}
// 1.5.3 根据 this.index 的值 给对应的 li 添加类名
this.imgBox.children[this.index].classList.add("active");
this.focus.children[this.index].classList.add("active");
}
// 2. 自动轮播
autoPlay() {
this.timer = setInterval(() => {
// 调用一个类似 move 函数的 方法
this.cut(true);
}, 2000);
}
// 3. 鼠标移入移出事件
mouseMove() {
// 3.1 鼠标移入 关闭定时器
this.ele.onmouseover = () => clearInterval(this.timer);
// 3.2 鼠标移出 开启定时器
this.ele.onmouseout = () => this.autoPlay();
}
// 4. 点击事件
clickBtn() {
this.ele.onclick = (e) => {
if (e.target.className === "left") {
// 切换上一页
this.cut(false);
}
if (e.target.className === "right") {
// 切换下一页
this.cut(true);
}
if (e.target.className === "focus_item") {
// 切换某一页
// console.log(e.target.dataset.id - 0);
this.cut(e.target.dataset.id - 0);
}
};
}
}
2. 选项卡
html和js文件
<!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>Document</title>
<style>
* {
padding: 0;
margin: 0;
}
ul,
ol {
list-style: none;
}
.header {
width: 600px;
height: 50px;
line-height: 50px;
text-align: center;
background-color: aqua;
display: flex;
}
.header li {
width: 200px;
}
.content {
width: 600px;
height: 400px;
line-height: 400px;
text-align: center;
font-size: 100px;
}
.content li {
display: none;
}
.header .active {
background-color: coral;
}
.content .active {
display: block;
background-color: forestgreen;
}
</style>
</head>
<body>
<div class="box1">
<ul class="header">
<li class="active">header_1</li>
<li>header_2</li>
<li>header_3</li>
</ul>
<ol class="content">
<li class="active">content_1</li>
<li>content_2</li>
<li>content_3</li>
</ol>
</div>
<div class="box2">
<ul class="header">
<li class="active">header_1</li>
<li>header_2</li>
<li>header_3</li>
</ul>
<ol class="content">
<li class="active">content_1</li>
<li>content_2</li>
<li>content_3</li>
</ol>
</div>
<script>
class Tabs {
// 构造器, 类似 构造函数的函数体
constructor(ele) {
this.ele = document.querySelector(ele)
this.hLi = [...this.ele.querySelectorAll('.header li')]
this.cLi = [...this.ele.querySelectorAll('.content li')]
// 创建 选项卡的一些 代码.....
this.init()
}
// 下边的位置全都是书写原型的位置
init() {
let that = this
this.hLi.forEach(function (item, index) {
item.onclick = function () {
// 1. 给所有的 li 全都取消类名
that.hLi.forEach(function (li, liIndex) {
li.classList.remove('active')
that.cLi[liIndex].classList.remove('active')
})
// 2. 给当前点击的 li 添加类名
item.classList.add('active')
that.cLi[index].classList.add('active')
}
})
}
}
new Tabs('.box1')
new Tabs('.box2')
</script>
</body>
</html>