初学 class 类,打包 tab 栏切换

使用class类打包tab栏切换

一、搭建html结构

  <main>
    <h4 style="user-select: none;">JS 面向对象,动态添加标签页</h4>

    <div class="tabsbox" id="tab">
      <!-- tab标签 -->
      <nav class="firstnav">
        <!-- tab栏标题 -->
        <ul>
          <li class="liactive"><span>测试1</span><span class="close">×</span></li>
          <li><span>测试2</span><span class="close">×</span></li>
          <li><span>测试3</span><span class="close">×</span></li>
        </ul>
        <!-- 添加按钮 -->
        <div class="tabadd">
          <span>+</span>
        </div>
      </nav>

      <!-- tab 内容 -->
      <div class="tabscon">
        <section class="conactive">内容1</section>
        <section>内容2</section>
        <section>内容3</section>
      </div> 
    </div>
  </main>

效果图在这里插入图片描述

二、css 样式

* {
  margin: 0;
  padding: 0;
}
main {
  width: 900px;
  margin: 0px auto;
}
h4 {
  text-align: center;
  line-height: 50px;
}
.tabsbox {
  width: 800px;
  margin: 0 auto;
  border: 1px solid orange;
}
.firstnav {
  position: relative;
  line-height: 40px;
  height: 40px;
  text-align: center;
  border-bottom: 1px solid #999;
}
.firstnav li {
  list-style: none;
  width: 100px;
  float: left;
  border-right: 1px solid #999;
  position: relative;
  cursor: pointer;
}
.firstnav li span {
  /* 阻止用户选中文字 */
  user-select: none;
}
.firstnav li.liactive::after {
  content: "";
  width: 100%;
  height: 2px;
  position: absolute;
  z-index: 11;
  bottom: -2px;
  left: 0;
  background: #fff;
}
.firstnav .close {
  cursor: pointer;
  position: absolute;
  right: 2px;
  top: 2px;
  font-size: 14px;
  color: #666;
  border: 1px solid #ccc;
  width: 14px;
  height: 14px;
  line-height: 12px;
  text-align: center;
  border-radius: 100%;
}
.tabscon {
  height: 300px;
  white-space: normal;
}
.tabscon input {
  width: 100%;
  height: 80px;
}
.tabscon section {
  padding: 30px;
  display: none;
}
.tabscon section.conactive {
  display: block;
}
.tabadd {
  position: absolute;
  padding: 0 10px;
  right: 10px;
  top: 0px;
  font-size: 20px;
  cursor: pointer;
  user-select: none;
}
input {
  width: 50px;
  line-height: 20px;
}

三、js

// 用来保存类中的 this 
let that

// 1. 定义 Tab 栏类
class Tab {
    constructor(selector) { // 这里的 selector = #tab
        // 2. 定义公共的属性
        this.main = document.querySelector(selector) //tab 栏主容器
        this.ul = this.main.querySelector('ul') //标题栏
        this.add = this.main.querySelector('.tabadd') //添加按钮
        this.content = this.main.querySelector('.tabscon') //内容区域
        this.lis = this.ul.children //所有的标题
        this.secs = this.content.children //所有的内容
        

        // 4. 在页面加载完的时候就调用初始化 init 方法(因为类似于点击切换这种操作要在一开始就调用)
        this.init()

        // 将类属性定义中的 this 保存到 that 变量中去
        that = this // that 表示利用 Tab 栏类创建的对象
    }

    // 4. 初始化
    init() {
        // 遍历所有的 li ,注册事件
        for (let i = 0; i < this.lis.length; i++) {
            // 循环给 li 注册点击事件
            this.lis[i].addEventListener('click', this.toggleTab)
            // 5.1 同时将 li 的索引号保存到当前的元素对象中去,作为一个属性存在
            this.lis[i].index = i
            // 给删除按钮注册点击事件
            this.lis[i].children[1].addEventListener('click', this.deleteTab)
            // 给标题的 span 标签注册双击事件
            this.lis[i].children[0].addEventListener('dblclick', this.editorTab)

            this.content.children[i].addEventListener('dblclick', this.editorTab)
        }

        // 给 新增按钮 注册点击事件
        this.add.addEventListener('click', this.addTab)

    }

    // 3.公共的方法:增加,删除,切换,修改
    // 切换
    toggleTab() {
        // 因为这里的 this 已经指向了当前选中的 li ,所以使用 全局变量 that 作为媒介
        // 遍历所有的 li 
        for (let i = 0; i < that.lis.length; i++) {
            // 排他思想
            // 删除所有 li 的类名
            that.lis[i].classList.remove('liactive')
            // 删除所有 content 的类名
            that.secs[i].classList.remove('conactive')
        }
        this.classList.add('liactive')

        // 5.2 选中当前应该显示的 content ,通过类名让当前 content 显示
        that.secs[this.index].classList.add('conactive')
    }
    // 增加
    addTab() {
        // 点击增加一个子元素
        that.ul.innerHTML += '<li><span>new tab</span><span class="close">×</span></li>'
        that.content.innerHTML += '<section>新的内容页</section>'

        // 因为在增加子元素的时候,页面重绘了,所以重启初始化
        that.init()

        // 默认显示新增的内容:模拟点击一次最后的 tab标题
        that.ul.lastElementChild.click()
        // that.lis[that.lis.length - 1].click()
    }
    // 删除
    deleteTab(e) {
        e.stopPropagation()

        let index = this.parentNode.index

        if(this.parentNode.className == 'liactive'){
            if(index != 0){
                that.lis[index - 1].click()
            }else{
                that.lis[index + 1].click()
            }
        }

        that.ul.removeChild(this.parentNode)
        that.content.removeChild(that.secs[index])
        that.init()
    }
    //编辑
    editorTab() {
        this.innerHTML = '<input type="text" value="'+this.innerText+'">'
        this.children[0].select()
        this.children[0].addEventListener('blur',function() {
            this.parentNode.innerText = this.value
        })
        this.children[0].addEventListener('keyup',function(e) {
            if (e.keyCode === 13){
                this.blur()
            }
        })
    }
}

new Tab('#tab')

四、注意点

  1. 获取元素其实就是在构造函数里面添加属性
  2. 实现动态增删改查就是类方法
  3. init 初始化可以在页面已加载完成就绑定完成事件,不需要手动调用
  4. 注意类中的调用自身属性或方法前面一定要加 this
  5. 注意 this 的指向问题,函数看调用,事件看绑定者
  6. 注意冒泡事件对代码执行的影响
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值