实现效果
点击x 可删除 点击+可新增 点击tab栏可进行切换 双击可修改内容
HTML CSS
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>js面向对象动态添加标签页</title>
<link rel="stylesheet" href="../css/tab.css">
</head>
<body>
<main>
<h3> js面向对象动态添加标签页</h3>
<div class="tabbox" id="tab">
<!-- tab -->
<nav class="firstnav">
<ul>
<li class="liactive"><span>测试1</span><span class="off">x</span></li>
<li ><span>测试2</span><span class="off">x</span></li>
<li ><span>测试3</span><span class="off">x</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>
</body>
<script src="../js/tab.js"></script>
</html>
CSS
*{
margin: 0;
padding: 0;
}
h3{
text-align: center;
}
#tab{
width: 800px;
height: 300px;
border: 1px solid black;
margin: 0 auto;
}
.firstnav{
width: 100%;
height: 50px;
/* border: 1px solid black; */
display: flex;
justify-content: space-between;
}
.firstnav ul{
display: flex;
height: 50px;
}
.firstnav ul li input{
width: 80%;
}
.tabscon input{
width: 100%;
height: 50px;
}
.tabadd{
height: 40px;
line-height: 40px;
width: 20px;
padding: 5px;
}
.firstnav ul li {
list-style: none;
border-right: 1px solid black;
border-bottom: 1px solid black;
height: 40px;
line-height: 40px;
width: 70px;
padding: 5px;
display: flex;
justify-content: space-between;
}
.firstnav ul .liactive{
border-bottom: 1px solid lemonchiffon;
background-color: lemonchiffon;
}
.tabscon{
padding: 20px;
background-color: lemonchiffon;
height: 210px;
width: 760px;
}
.tabscon section{
display: none;
}
.tabscon .conactive{
display: block;
}
JS
let that
class Tab{
constructor(id){
//保存当前this指向
that=this
//查找元素
this.main= document.querySelector(id)
this.add=this.main.querySelector('.tabadd')
this.ul=this.main.querySelector('.firstnav ul:first-child')
this.tabscon=this.main.querySelector('.tabscon')
//调用初始化方法
this.init()
}
init(){
//更新元素个数
this.updateNode()
//循环绑定点击事件
this.add.οnclick=this.addTab
for (let i = 0; i < this.lis.length; i++) {
this.lis[i].index=i
this.lis[i].οnclick=this.toggleTab
this.remove[i].οnclick=this.removeTab
//双击事件
this.spans[i].οndblclick=this.editTab
this.sections[i].οndblclick=this.editTab
}
}
//点击添加按钮后 元素个数会动态改变
updateNode(){
this.lis=this.main.querySelectorAll('li')
this.sections=this.main.querySelectorAll('section')
this.remove=this.main.querySelectorAll('.off')
this.spans=this.main.querySelectorAll('.firstnav li span:first-child')
}
//tab栏切换
toggleTab(){
that.clearClass()
// console.log(this.index);
this.className='liactive'
that.sections[this.index].className='conactive'
}
//清楚其他li和section的样式
clearClass(){
for (let i = 0; i < this.lis.length; i++) {
this.lis[i].className=''
this.sections[i].className=''
}
}
//添加tab栏
addTab(){
//清楚其他选中样式
that.clearClass()
//随机数
let random =Math.random()
// 添加的标签 li section
let li='<li class="liactive"><span>new</span><span class="off">x</span></li>'
let section ='<section class="conactive">'+random+'</section>'
//文本解析为HTML元素
that.ul.insertAdjacentHTML('beforeend',li)
that.tabscon.insertAdjacentHTML('beforeend',section)
//重新调用初始化方法
that.init()
}
//移除tab栏
removeTab(e){
//阻止冒泡
e.stopPropagation();
//保存父级index值 作为tab栏选中按钮
let index= this.parentNode.index
// 删除当前选中元素
that.lis[index].remove()
that.sections[index].remove()
that.init()
//当前选中元素不为移除元素 直接返回
if (document.querySelector('.liactive')) return
//移除元素为最后一个 则自动选择前一个
index--
that.lis[index]&&that.lis[index].click()
}
//编辑tab栏文字
editTab(){
//保存当前内容
let str =this.innerHTML
// 双击禁止选中文字
window.getSelection ? window.getSelection().removeAllRanges() : document.selection.empty();
//双击替换为输入框
this.innerHTML='<input type="text"/>'
let input =this.children[0]
//当前文字赋值给input框 并保持选中
input.value=str
input.select()
//鼠标移出输入框 保存当前值
input.οnblur=function () {
this.parentNode.innerHTML= this.value
}
//回车自动保存
input.οnkeyup=function (e) {
if (e.keyCode === 13) {
//手动调用鼠标方法
this.blur()
}
}
}
}
new Tab('#tab')
知识点总结
面向对象开发
双击禁止选择文字
// 双击禁止选中文字
window.getSelection ? window.getSelection().removeAllRanges() : document.selection.empty();
insertAdjacentHTML() 方法将指定的文本解析为 Element 元素,并将结果节点插入到DOM树中的指定位置。它不会重新解析它正在使用的元素,因此它不会破坏元素内的现有元素。这避免了额外的序列化步骤,使其比直接使用innerHTML操作更快。
DOMString,表示插入内容相对于元素的位置,并且必须是以下字符串之一:
‘beforebegin’:元素自身的前面。
‘afterbegin’:插入元素内部的第一个子节点之前。
‘beforeend’:插入元素内部的最后一个子节点之后。
‘afterend’:元素自身的后面。
element.insertAdjacentHTML(position, text);
阻止冒泡
e.stopPropagation();
onblur事件 失去焦点
object.onblur=function(){SomeJavaScriptCode};