面向对象 tab栏切换

在B站看到的学习视频 传送门
首先看一下效果

在这里插入图片描述

需求介绍

  1. 点击tab栏,实现切换效果
  2. 点击+号,实现添加tab项和内容项
  3. 点击X号,可以删除当前的tab项和内容项
  4. 点击tab项文字或者内容,可以修改里面的文字

抽取对象:tab对象

  1. 该对象具有切换功能
  2. 该对象具有添加功能
  3. 该对象具有修改功能
  4. 该对象具有删除功能

项目分析

项目初始化

应该让所有的li section X 已经添加按钮 都绑定事件

切换

  • 让当前点击的li具有类名,兄弟去除类名
  • 点击li的时候this指向为li,不是#tab,所以要注意this指向

添加

  • 点击添加的时候,创建li和section
  • 点击添加的时候,当前为选中,兄弟去掉类名
  • 把添加的添加到对应的父组件中

不推荐使用createElement的原因是因为,li的元素比较多
element.insertAdjacentHtml() 可以直接讲字符串格式元素添加到父元素中

  • 每次添加完成时候,要重新获取到新的li和section,绑定新的事件
  • 点击的时候,this指向的是+按钮,注意this指向

删除

  • 点击 X 的时候,可能会冒泡到父亲的切换事件, 要记得阻止冒泡
  • 点击 X 的时候,他没有索引值,但是他的父亲有
  • 每次删除完,重新获取一遍新的元素

编辑

  • 双击选中 改变内容

如果双击的话 会默认选中文字,此时需要禁止双击选中文字
window.getSelection?window.getSelection().removeAllRanges():document.section.empty();

  • 核心思路:双击文字时,里面成功一个文本框,当时去焦点或者摁下回车后,把文本框中的值赋给原先的元素
  • 让文本框处于选中状态
  • 当我们离开文本框的时候,把文本框的赋给font

话不多说上代码

JS

var _that;
class Tab {
    
    
  constructor() {
    
    
    _that=this
    //首先要获取所有的元素,便于添加事件
    this.tab=document.querySelector('#tab');

    this.ul=this.tab.querySelector('ul')
    this.section=this.tab.querySelector('.section')

    this.add=this.tab.querySelector('.add')
    
    this.init()
  }
  updateNode(){
    
    
    //每次操作完成之后,需要从新获取li和section
    this.liList=this.tab.querySelectorAll('li')
    this.sectionList=this.tab.querySelectorAll('section')
    this.xList = this.tab.querySelectorAll('li span')
    this.fontList=this.tab.querySelectorAll('li font')
  }
  init(){
    
    
    //初始化,让所有li X 都绑定事件
    this.updateNode()
    for(var i =0;i<this.liList.length;i++){
    
    
      this.liList[i].index=i
      this.liList[i].onclick=this.toggleTab
      this.xList[i].onclick=this.delTab
      this.fontList[i].ondblclick=this.editTab
      this.sectionList[i].ondblclick=this.editTab
    }
    this.add.onclick=this.addTab
  }
  clearClass(){
    
    
  	//去除类名
    for(var i =0;i<this.liList.length;i++){
    
    
      this.liList[i].className=''
      this.sectionList[i].className=''
    }
  }
  toggleTab(){
    
    
    //点击li的时候this指向为li,不是#tab,所以要注意this指向
    _that.clearClass()
    this.className='liActive'
    _that.sectionList[this.index].className='sectionActive'
  }
  addTab(){
    
    
    //点击的时候,this指向的是+按钮,注意this指向
    //点击添加的时候,创建li和section
    _that.clearClass()//每次点击添加的时候,当前为选中,兄弟去掉类名

    var random=Math.random()
    var li='<li class="liActive"> <font>新选项卡</font> <span>X</span></li>'
    var section='<section class="sectionActive">选项卡'+random+'</section>'

    //把添加的添加到对应的父组件中
    //不推荐使用createElement的原因是因为,li脸的元素比较多
    // element.insertAdjacentHtml() 可以直接讲字符串格式元素添加到父元素中
    _that.ul.insertAdjacentHTML('beforeend',li)
    _that.section.insertAdjacentHTML('beforeend',section)
    //每次添加完成时候,要重新获取到新的li和section,绑定新的事件
    _that.init()
  }
  delTab(e){
    
    
    //点击 X 的时候,可能会冒泡到父亲的切换事件, 阻止冒泡
    e. stopPropagation()
   
    //点击 X 的时候,他没有索引值,但是他的父亲有
    var index=this.parentNode.index
    //点击 X 删除对应索引的 li section
    //remove() 可以直接删除指定的元素
    _that.liList[index].remove()
    _that.sectionList[index].remove()

    //每次删除完,重新获取一遍新的元素
    _that.init()

    //当选中的不是选中状态时,选中状态不变
    if(document.querySelector('.liActive')) return;

    //当删除选中状态的li时,让他的前一个li为选中状态
      index--
    
    //让他前一个li做一次点击事件  
    //第一个的时候,没有前一个,做一个判断
    _that.liList[index] &&  _that.liList[index].click()
   
  }
  editTab(){
    
    
    var str=this.innerHTML  
    //双击选中  改变内容
    // 如果双击的话 会默认选中文字,此时需要禁止双击选中文字
    window.getSelection?window.getSelection().removeAllRanges():document.section.empty();
    //核心思路:双金文字时,里面成功一个文本框,当时去焦点或者摁下回车后,把文本框中的值赋给原先的元素
    this.innerHTML='<input type="text" />'
    var input = this.children[0]
    input.value=str
    //让文本框处于选中状态
    input.select()
    //当我们离开文本框的时候,把文本框的值给了font
    input.onblur=function(){
    
    
      this.parentNode.innerHTML=this.value
    }
    //按下回车的时候,把文本框的值,给了font
    input.onkeyup=function(e){
    
    
      if(e.keyCode===13){
    
    
        //手动调用input失焦事件
        this.blur()
      }
    }
  }

}
new Tab()

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>
    ul{
     
     
      padding: 0;
      margin: 0;
    }
    #tab{
     
     
      width: 600px;
      height: 400px;
      position: relative;
      border: 1px solid pink;
    }
    ul{
     
     
      overflow: hidden;
      border-bottom: 1px solid red;
    }
    ul li{
     
     
      box-sizing: border-box;
      list-style: none;
      height: 50px;
      width: 80px;
      border: 1px solid red;
      float: left;
      position: relative;
      text-align: center;
      line-height: 50px;
    }
    ul li span{
     
     
      position: absolute;
      right: 0;
      top: 0;
      width: 15px;
      height: 15px;
      color: white;
      background: black;
      text-align: center;
      line-height: 15px;
    }
    input{
     
     
      width: 100%;
    }
    section input{
     
     
      height: 100px;
      width: 90%;
    }
    .section{
     
     
      width: 100%;
      height: 350px;
    }
    section{
     
     
      display: none;
      width: 100%;
      height: 100%;
    }
    .add{
     
     
      font-weight: bold;
      position: absolute;
      right: 5px;
      top: 5px;
      border: 1px salmon solid;
      padding: 5px;
    }
    .liActive{
     
     
      background-color: antiquewhite;
    }
    .sectionActive{
     
     
      display: block;
    }
  </style>
</head> 
<body>
  <div id="tab">
    <ul>
      <li class="liActive"> <font>测试1</font> <span>X</span></li>
      <li> <font>测试2</font> <span>X</span></li>
      <li><font>测试3</font> <span>X</span></li>
    </ul>
    <div class="add">+</div>
    <div class="section">
      <section class="sectionActive">li1</section>
      <section>测试2</section>
      <section>测试三</section>
    </div>
  </div>
</body>
<script src="./index.js"></script>
</html>

猜你喜欢

转载自blog.csdn.net/weixin_45972345/article/details/115052736