效果图
一.css
<style>
*{
margin: 0;
padding:0;
}
ul,ol,li{
list-style: none;
}
.cont{
width: 800px;
height: 600px;
border: 5px solid #333;
margin: 0 auto;
display: flex;
flex-direction: column;
}
.cont ul{
width: 100%;
height: 60px;
display: flex;
}
.cont ul li{
flex:1;
font-size: 35px;
color: #fff;
border-left: 2px solid blue;
border-right: 2px solid blue;
background: hotpink;
display: flex;
justify-content: center;
align-items: center;
}
.cont ol{
flex:1;
position: relative;
}
.cont ol li{
width: 100%;
height: 100%;
font-size: 150px;
display: flex;
justify-content: center;
align-items: center;
position: absolute;
top:0;
left:0;
background: burlywood;
display: none;
}
/* 按钮标签 哪个标签有这个属性,哪个就显示特殊背景颜色 */
.cont ul li.active{
background: skyblue;
color: black;
}
/* 内容标签 哪个标签有这个属性,哪个就显示 */
.cont ol li.active{
display: flex;
}
</style>
二.html
<div class="cont">
<ul>
<li name="ulli" class="active">按钮1</li>
<li name="ulli" >按钮2</li>
<li name="ulli" >按钮3</li>
</ul>
<ol>
<li name="olli" class="active">内容1</li>
<li name="olli" >内容2</li>
<li name="olli" >内容3</li>
</ol>
</div>
三.JS方法1:面向过程之事件委托形式
获取父级div标签对象
var oDiv = document.querySelector('div');
// 获取标签对象
var ullis = document.querySelectorAll('ul li');
var ollis = document.querySelectorAll('ol li');
oDiv.onclick = function(e){
if(e.target.getAttribute('name') === 'ulli'){
// 1,给所有的li标签,清除样式
ullis.forEach(function(item,key){
item.className = '';
ollis[key].className = '';
// 给item,也就是ul中的li标签,定义属性
item.setAttribute('index',key);
})
e.target.className = 'active';
ollis[e.target.getAttribute('index')].className = 'active';
}
}
四.JS方法2:面向对象的方法1
创建一个对象,这个对象中有属性有方法
属性是需要操作的标签等
方法就是实现选项卡效果的程序
// 定义构造函数
// 参数:需要执行的tab切换的标签对象,是所有需要执行选项卡效果标签的父级
// 面向对象方法1,建立变量,存储this
function SetTab1(ele){
// 先要单独,接收存储参数
this.ele = ele;
// 通过参数,来获取需要的标签对象
this.ullis = ele.querySelectorAll('ul li');
this.ollis = ele.querySelectorAll('ol li');
// 在构造函数中,定义的this指向的是实例化对象
}
// 定义构造函数的方法
SetTab1.prototype.fun = function(){
// 选项卡思路
// 给所有的ul中的li,添加点击事件,点击时,清除所有的ul,ol中li的样式
// 给当前点击的li,添加样式,再给对应的ol中的li,添加样式
// 定义一个变量,专门存储this指向
// 此时的this指向,还是 实例化对象
// oldThis 变量中 存储的就是 实例化对象
let oldThis = this;
// 循环遍历 ul中所有的li
// 这里的 this.ullis 指向的是 实例化对向中的属性 this.ullis 中存储的数据
// this.ullis this.ollis this.ele 其中的this,应该都是指向实例化对象
this.ullis.forEach(function(item,key){
// 给 li标签添加点击事件
item.addEventListener('click' , function(){
// 在点击事件中,此时this指向的是绑定点击事件的标签 item
// 就不是 实例化对象了
// 此时,要想正确调用 实例化对象属性的属性值
// 必须 使用 一个 指向是 实例化对象的内容
// 先循环遍历所有的ul和ol中的li,清除css样式
oldThis.ullis.forEach(function(item2 , k){
item2.className = '';
oldThis.ollis[k].className = '';
})
// 给点击的ul,li添加样式
item.className = 'active';
// 给对应的ol,li添加样式
oldThis.ollis[key].className = 'active';
})
})
}
wu .JS方法2:面向对象的方法2
// 面向对象方法2,箭头函数
function SetTab2(ele){
// 先要单独,接收存储参数
this.ele = ele;
// 通过参数,来获取需要的标签对象
this.ullis = ele.querySelectorAll('ul li');
this.ollis = ele.querySelectorAll('ol li');
// 在构造函数中,定义的this指向的是实例化对象
}
// 定义构造函数的方法
// 这里的function不能改为箭头函数,里面的都改
SetTab2.prototype.fun = function(){
// 将构造函数中,所有的函数,都写成箭头函数
// this 都会指向父级,最终都指向 实例化对象
this.ullis.forEach( (item,key)=>{
// 把普通的函数,改为箭头函数,this指向就是父级程序的this指向
// 也就是 实例化对象了
// 如果不改,this指向的是绑定事件的标签,也就是item
item.addEventListener('click' , ()=>{
// 这里的forEach也要改为箭头函数,不然this指向的是window
this.ullis.forEach((item2 , k)=>{
item2.className = '';
this.ollis[k].className = '';
})
// 给点击的ul,li添加样式
item.className = 'active';
// 给对应的ol,li添加样式
this.ollis[key].className = 'active';
})
})
}
// 获取标签对象
const oDiv = document.querySelector('div');
// 通过构造函数,生成实例化对象
// const tabs1 = new SetTab1(oDiv);
// console.log(tabs1)
// 调用实例化对象中的方法,来执行程序,实现选项卡效果
// tabs1.fun();
const tabs2 = new SetTab2(oDiv);
tabs2.fun()
特别注意:
调用构造函数,尤其是封装了方法的构造函数,必须要在定义构造函数之后,来调用
如果先调用,可以调用构造函数,也可以生成实例化对象
实例化对象中,也有属性
但是,对 构造函数 prototype 赋值定义方法,不会提前执行
生成的实例化对象,就没有绑定方法
面向对象语法,最关键的就是this的使用
一定要分清楚,每一个函数中,this的指向
常用 方法1: 找变量,存储this指向
方法2: 将function,写成 箭头函数,this为父级程序this