面向对象案例:Tab栏切换
面向对象案例
面向对象版Tab栏切换
功能需求:
-
点击 Tab 栏,可以切换效果。
-
点击 + 号,可以添加 Tab 项和内容项。
-
点击 x 号,可以删除当前的 Tab 项和内容项。
-
双击 Tab 项文字或者内容项文字,可以修改里面的文字内容。
步骤:
- 抽取对象: Tab 对象
- 分析对象具有的功能:
- 该对象具有切换功能
- 该对象具有添加功能
- 该对象具有删除功能
- 该对象具有修改功能
- 具体代码如下:
var that
class Tab{
constructor(id){
// 获取元素
that = this
this.main = document.querySelector(id)
this.add = this.main.querySelector('.tabadd')
// li的父元素
this.ul = this.main.querySelector('.firstnav ul:first-child')
// section 的父元素
this.fsection = this.main.querySelector('.tabscon')
this.init()
}
init(){
this.updateNode()
// init 初始化操作让相关的元素绑定事件
this.add.onclick = this.addTab
for(var i=0;i<this.lis.length;i++){
this.lis[i].index = i
this.lis[i].onclick = this.toggleTab
this.remove[i].onclick = this.removeTab
this.spans.ondbclick = this.editTab
this.sections.ondbclick = this.editTab
}
}
// 因为我们动态添加元素,需要重新获取对应的元素
updateNode(){
this.lis = this.main.querySelectorAll('li')
this.sections = this.main.querySelectorAll('section')
this.remove = this.main.querySelector('.icon-guanbi')
this.spans = this.main.querySelectorAll('.firstnav li span:first-child')
}
// 1. 切换功能
toggleTab(){
that.claerClass()
this.className = 'liactive'
that.sections[this.index].className = 'conactive'
}
// 清除所有 li 和 section 的类
claerClass(){
for(var i=0;i<this.lis.length;i++){
this.lis[i].className = ''
this.sections[i].className = ''
}
}
// 2. 添加功能
addTab(){
that.claerClass()
// 点击 + 可以实现添加新的选项卡和内容
// 第一步:创建新的选项卡 li 和新的内容 section
var li = '<li class="liactive"><span>测试1</span><span class="iconfont icon-guanbi"></span></li>'
var section = '<section class="conactive">测试1</section>'
// 第二步:把创建的两个元素追加到对应的父元素中
// 以前的做法:动态创建元素 createElement ,但是元素里面的内容较多,需要 innerHTML 赋值,再通过 appendChild 追加到父元素里面
// 现在的高级做法:利用 insertAdjacentHTML() 可以直接把字符串格式元素添加到父元素中
// appendChild 不支持追加字符串的子元素, insertAdjacentHTML 支持追加字符串的元素
that.ul.insertAdjacentHTML('beforeend',li)
that.fsection.insertAdjacentHTML('beforeend',section)
that.init()
}
// 3. 删除功能
// 1. 点击 x 可以删除当前的 li 选项卡和当前的 section
// 2. x 是没有索引号的,但是它的父亲 li 有索引号,这个索引号正是我们想要的索引号
// 3. 核心思路是:点击 x 号可以删除这个索引号对应的 li 和 section
removeTab(e){
// 阻止冒泡使用 stopPropagation() 方法,防止触发 li 的切换点击事件
e.stopPropagation()
var index = this.parentNode.index
// 根据索引号删除对应的 li 和 section,remove() 方法可以直接删除指定的元素
that.lis[index].remove()
that.sections[index].remove()
that.init()
// 当我们删除的不是选中状态的这个 li 的时候,原来的选中状态 li 保持不变
if(document.querySelector('liactive')) return
// 当我们删除了选中状态的这个 li 的时候,让他的前一个 li 处于选中状态
index--
// 手动调用我们的点击事件,不需要鼠标触发
that.lis[index] && that.lis[index].click()
}
// 4. 修改功能
// 双击选项卡 li 或 section 里面的文字,可以实现修改功能
// 双击事件:ondblclick
// 如果双击文字,会默认选定文字,此时需要双击禁止选中文字
// window.getSelection?window.getSelection().removeAllRanges():document.selection.empty
// 核心思路是:双击文字的时候,在里面生成一个文本框,当失去焦点或者按下回车然后把文本框输入的值给原先元素即可
editTab(){
var str = this.innerHTML
// 双击禁止选定文字
window.getSelection?window.getSelection().removeAllRanges() : document.selection.empty
this.innerHTML = '<input type="text" />'
var input = this.children[0]
input.value = str
input.select() // 文本框里面的文字处于选定状态
// 当我们离开文本框就把文本框里面的值给 span
input.onblur = function(){
this.parentNode.innerHTML = this.value
}
// 按下回车也可以把文本框里面的值给 span
input.onkeyup = function(e){
if(e.keyCode === 13){
// 手动调用表单失去焦点事件,不需要鼠标离开操作
this.blur()
}
}
}
}
new Tab('#tab')
总结
涉及到的知识点:
insertAdjacentHTML()
语法:element.insertAdjacentHTML(position,text)
// text 是要被解析为 HTML 或 XML,并插入到 DOM 树中的字符串。
beforebegin
:元素自身的前面。afterbegin
:插入元素内部的第一个子节点之前。beforeend
:插入元素内部的最后一个子节点之后。afterend
:元素自身的后面。
ondbclick
:双击事件。onkeyup
:键盘弹起事件。window.getSelection?window.getSelection().removeAllRanges() : document.selection.empty
:双击禁止选定文字。- 使用
stopPropagation()
方法阻止冒泡。 remove()
方法可以直接删除指定的元素。