运行效果
html代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>面向对象编程</title>
</head>
<body>
<div id="app">
<div class="lc-tab">
<div class="lc-tab__add">+</div>
<div class="lc-tab__nav">
<div class="lc-tab__item active">
<span class="ellipsis">Tab1</span>
<input type="text">
<span class="lc-tab__del">x</span>
</div>
<div class="lc-tab__item">
<span class="ellipsis">Tab2</span>
<input type="text">
<span class="lc-tab__del">x</span>
</div>
<div class="lc-tab__item">
<span class="ellipsis">Tab3</span>
<input type="text">
<span class="lc-tab__del">x</span>
</div>
</div>
<div class="lc-tab__page">
<div class="lc-tab__content active">
<span>Page1</span>
<textarea rows="10" cols="30"></textarea>
</div>
<div class="lc-tab__content">
<span>Page2</span>
<textarea rows="10" cols="30"></textarea>
</div>
<div class="lc-tab__content">
<span>Page3</span>
<textarea rows="10" cols="30"></textarea>
</div>
</div>
</div>
</div>
</body>
</html>
css代码:
.lc-tab {
position: relative;
border: 2px solid #ddd;
}
.lc-tab .lc-tab__add {
position: absolute;
top: 10px;
right: 10px;
width: 20px;
height: 20px;
border: 2px solid #000;
text-align: center;
line-height: 20px;
cursor: pointer;
}
.lc-tab .lc-tab__nav {
height: 50px;
border-bottom: 2px solid #ddd;
}
.lc-tab .lc-tab__nav .lc-tab__item {
float: left;
position: relative;
min-width: 60px;
max-width: 120px;
padding: 0 10px;
border-right: 2px solid #ddd;
text-align: center;
line-height: 50px;
cursor: pointer;
}
.lc-tab .lc-tab__nav .lc-tab__item input {
display: none;
width: calc(100% - 25px);
height: 30px;
}
.lc-tab .lc-tab__nav .lc-tab__item input.show {
display: inline;
}
.lc-tab .lc-tab__nav .lc-tab__item.active {
border-bottom: 2px solid #fff;
}
.lc-tab .lc-tab__nav .lc-tab__item .lc-tab__del {
position: absolute;
top: -1px;
right: -1px;
width: 15px;
height: 15px;
line-height: 15px;
color: #fff;
background-color: #000;
cursor: pointer;
}
.lc-tab .lc-tab__page {
position: relative;
}
.lc-tab .lc-tab__page .lc-tab__content {
display: none;
width: 100%;
min-height: 200px;
text-align: center;
line-height: 100%;
}
.lc-tab .lc-tab__page .lc-tab__content textarea {
display: none;
}
.lc-tab .lc-tab__page .lc-tab__content textarea.show {
display: inline;
}
.lc-tab .lc-tab__page .lc-tab__content.active {
display: block;
}
js代码:
export default class Tab {
constructor (el) {
this.name = 'Tab';
this.tab = document.getElementsByClassName(el)[0];
this.tabNav = this.tab.getElementsByClassName('lc-tab__nav')[0];
this.tabPage = this.tab.getElementsByClassName('lc-tab__page')[0];
this.tabNavItems = this.tabNav.getElementsByClassName('lc-tab__item');
this.tabPageContents = this.tabPage.getElementsByClassName('lc-tab__content');
this.addTabBtn = this.tab.getElementsByClassName('lc-tab__add')[0];
this.activeIndex = 0;
this.init();
}
init () {
this.bindEvent();
}
bindEvent () {
this.addTabBtn.onclick = this.addTab.bind(this);
const len = this.tabNavItems.length;
for (let i = 0; i < len; i++) {
this.tabNavItems[i].onclick = this.toggleTab.bind(this);
this.tabNavItems[i].ondblclick = this.editTab.bind(this);
const delBtn = this.tabNavItems[i].getElementsByClassName('lc-tab__del')[0];
delBtn.onclick = this.delTab.bind(this);
const input = this.tabNavItems[i].getElementsByTagName('input')[0];
input.onblur = this.saveTab.bind(this);
this.tabPageContents[i].ondblclick = this.editTab.bind(this);
const textarea = this.tabPageContents[i].getElementsByTagName('textarea')[0];
textarea.onblur = this.saveTab.bind(this);
}
}
// 插入page页
addTab () {
this.clearActive();
const nav = document.createElement('div');
nav.setAttribute('class', 'lc-tab__item');
nav.classList.add('active');
nav.innerHTML = `
<span class="ellipsis">Tab</span>
<input type="text">
<span class="lc-tab__del">x</span>
`;
const page = document.createElement('div');
page.setAttribute('class', 'lc-tab__content');
page.classList.add('active');
page.innerHTML = `
<span>Page</span>
<textarea rows="10" cols="30"></textarea>
`;
this.tabNav.appendChild(nav);
this.tabPage.appendChild(page);
this.activeIndex = this.tabNavItems.length - 1;
this.bindEvent();
}
delTab (event) {
const e = event || window.event;
e.stopPropagation() || (e.cancelBubble = true);
let p = e.target.parentNode;
const index = [...this.tabNavItems].indexOf(p);
this.tabNav.removeChild(p);
this.tabPage.removeChild(this.tabPageContents[index]);
if (index == this.activeIndex) {
this.activeIndex = 0;
this.setActive(this.activeIndex);
}
}
toggleTab (event) {
this.clearActive();
const e = event || window.event;
const tab = e.currentTarget;
tab.classList.toggle('active');
const index = [...this.tabNavItems].indexOf(tab);
this.activeIndex = index;
this.tabPageContents[index].classList.toggle('active');
}
editTab (event) {
window.getSelection ? window.getSelection().removeAllRanges() : document.getSelection.empty();
const e = event || window.event,
tar = e.currentTarget;
let input;
if ([...tar.classList].indexOf('lc-tab__item') != -1) {
input = tar.getElementsByTagName('input')[0];
} else {
input = tar.getElementsByTagName('textarea')[0];
}
// 不知道为啥单写input.select()不管用
setTimeout(() => {
input.select();
}, 0);
const span = tar.getElementsByTagName('span')[0];
span.style.display = 'none';
input.value = span.innerText;
input.classList.add('show');
}
// 完成编辑
saveTab (event) {
const e = event || window.event,
tar = e.currentTarget,
p = tar.parentNode;
const txt = tar.value;
tar.classList.remove('show');
const tab = p.getElementsByTagName('span')[0];
tab.innerText = txt;
tab.style.display = 'block';
}
// 清除actice样式
clearActive () {
[...this.tabNavItems].forEach(ele => {
if ([...ele.classList].indexOf('active') != -1) {
ele.classList.toggle('active');
}
});
[...this.tabPageContents].forEach(ele => {
if ([...ele.classList].indexOf('active') != -1) {
ele.classList.toggle('active');
}
});
}
// 给某一个tab和page设置active类
setActive (index) {
const i = index || 0;
this.tabNavItems[i].classList.add('active');
this.tabPageContents[i].classList.add('active');
}
}