功能需求实现
- 点击tab栏,可以切换标签页
- 点击+号,可以添加tab栏和内容项
- 点击x号,可以删除当前的tab项和内容项
- 双击tab项文字或者内容项文字,可以修改里面的文字内容
抽象对象:Tab对象
- 该对象具有切换功能
- 该对象具有添加功能
- 该对象具有删除功能
- 该对象具有修改功能shoxain
class Tab {
constructor() {
}
//1.切换功能
toggleTab() {}
//2.添加功能
addTab() {}
// 3.删除功能
removeTab() {}
// 4.修改功能
editTab() {}
}
new Tab('#tab');
初始化对象 首先初始化 给相关元素绑定事件
class Tab {
constructor(id) {
//获取元素
this.main = document.querySelector(id);
this.lis = this.main.querySelectorAll('li');
this.sections = this.main.querySelectorAll('section');
this.init();
}
// 初始化
init(){
// init 初始化操作让相关元素绑定事件
for(var i =0;i<this.lis.length;i++){
// 存的是小li的索引号
this.lis[i].index = i;
this.lis[i].onclick = function() {
console.log(this.index);//测试一下看是不是绑定成功了
}
}
}
//1.切换功能
toggleTab() {}
//2.添加功能
addTab() {}
// 3.删除功能
removeTab() {}
// 4.修改功能
editTab() {}
}
new Tab('#tab');
1.切换功能模块
var that;
class Tab {
constructor(id) {
//获取元素
this.main = document.querySelector(id);
this.lis = this.main.querySelectorAll('li');
this.sections = this.main.querySelectorAll('section');
this.init();
that = this;
}
// 初始化
init(){
// init 初始化操作让相关元素绑定事件
for(var i =0;i<this.lis.length;i++){
// 存的是小li的索引号
this.lis[i].index = i;
this.lis[i].onclick = this.toggleTab;
}
}
//1.切换功能
toggleTab() {
// !!!!!一定注意this的指向问题
// console.log(this.index);
// 如果必须要清除所有样式 呢么必须使用最大的对象 也就是constructor里面的对象this
that.clearClass();
this.className = 'liactive';
// 必须用constrcutor 所以用that变量来使用另一个this this指向的lis[i]里面没有sections
that.sections[this.index].className = 'conactive';
}
clearClass() {
for(var i = 0;i<this.lis.length;i++){
this.lis[i].className = '';
this.sections[i].className = '';
}
}
//2.添加功能
addTab() {}
// 3.删除功能
removeTab() {}
// 4.修改功能
editTab() {}
}
new Tab('#tab');
2.添加功能模块
思路理解:
- 点击+号,可以添加tab栏和内容项
- 第一步 必须创建新的选项卡li和新的内容section
- 第二步 把创建的两个元素追加到对应的父元素里面去了
补充知识点:insertAdjacentHTML()
作用:
方法将指定的文本解析为 Element 元素,并将结果节点插入到 DOM 树中的指定位置。它不会重新解析它正在使用的元素,因此它不会破坏元素内的现有元素。这避免了额外的序列化步骤,使其比直接使用 innerHTML 操作更快。
参考链接:https://developer.mozilla.org/zh-CN/docs/Web/API/Element/insertAdjacentHTML
基础语法:
element.insertAdjacentHTML(position, text);
var that;
class Tab {
constructor(id) {
that = this;
//获取元素
this.main = document.querySelector(id);
this.add = this.main.querySelector('.tabadd');
// li的父元素
// css3选择器
this.ul = this.main.querySelector('.fisrstnav ul:first-child');
this.fsection = this.main.querySelector('.tabscon');
this.init();
}
// 获取所有的li和section
updateNode() {
this.lis = this.main.querySelectorAll('li');
this.sections = this.main.querySelectorAll('section');
}
// 初始化
init(){
this.updateNode();
this.add.onclick = this.addTab;
// init 初始化操作让相关元素绑定事件
for(var i =0;i<this.lis.length;i++){
// 存的是小li的索引号
this.lis[i].index = i;
this.lis[i].onclick = this.toggleTab;
}
}
//1.切换功能
toggleTab() {
// !!!!!一定注意this的指向问题
// console.log(this.index);
// 如果必须要清除所有样式 呢么必须使用最大的对象 也就是constructor里面的对象this
that.clearClass();
this.className = 'liactive';
// 必须用constrcutor 所以用that变量来使用另一个this this指向的lis[i]里面没有sections
that.sections[this.index].className = 'conactive';
}
clearClass() {
for(var i = 0;i<this.lis.length;i++){
this.lis[i].className = '';
this.sections[i].className = '';
}
}
//2.添加功能
addTab() {
that.clearClass();
var random = Math.random();
// alert(11); 测试用例
var li = '<li class="liactive"><span>新选项卡</span><span class="iconfont icon-guanbi"></span></li>';
var section = '<section class="conactive">测试1'+random+'</section>';
that.ul.insertAdjacentHTML('beforeend',li);
that.fsection.insertAdjacentHTML('beforeend',section);
that.init();
}
// 3.删除功能
removeTab() {}
// 4.修改功能
editTab() {}
}
new Tab('#tab');
3.删除功能模块
!!!y要注意元素的值是有变化的 所以必须实时更新数据
补充知识
remove()方法:Element.remove()
方法,把对象从它所属的 DOM 树中删除。
参考链接:https://developer.mozilla.org/zh-CN/docs/Web/API/Element/remove
语法使用:
node.remove();
var that;
class Tab {
constructor(id) {
that = this;
//获取元素
this.main = document.querySelector(id);
this.add = this.main.querySelector('.tabadd');
// li的父元素
// css3选择器
this.ul = this.main.querySelector('.fisrstnav ul:first-child');
this.fsection = this.main.querySelector('.tabscon');
this.init();
}
// 获取所有的li和section
updateNode() {
this.lis = this.main.querySelectorAll('li');
this.sections = this.main.querySelectorAll('section');
this.remove = this.main.querySelectorAll('.icon-guanbi');
}
// 初始化
init(){
this.updateNode();
this.add.onclick = this.addTab;
// init 初始化操作让相关元素绑定事件
for(var i =0;i<this.lis.length;i++){
// 存的是小li的索引号
this.lis[i].index = i;
this.lis[i].onclick = this.toggleTab;
this.remove[i].onclick = this.removeTab;
}
}
//1.切换功能
toggleTab() {
// !!!!!一定注意this的指向问题
// console.log(this.index);
// 如果必须要清除所有样式 呢么必须使用最大的对象 也就是constructor里面的对象this
that.clearClass();
this.className = 'liactive';
// 必须用constrcutor 所以用that变量来使用另一个this this指向的lis[i]里面没有sections
that.sections[this.index].className = 'conactive';
}
clearClass() {
for(var i = 0;i<this.lis.length;i++){
this.lis[i].className = '';
this.sections[i].className = '';
}
}
//2.添加功能
addTab() {
that.clearClass();
var random = Math.random();
// alert(11); 测试用例
var li = '<li class="liactive"><span>新选项卡</span><span class="iconfont icon-guanbi"></span></li>';
var section = '<section class="conactive">测试1'+random+'</section>';
that.ul.insertAdjacentHTML('beforeend',li);
that.fsection.insertAdjacentHTML('beforeend',section);
that.init();
}
// 3.删除功能
removeTab(e) {
// 消除冒泡现象 防止触发li的点击事件
e.stopPropagation();
var index = this.parentNode.index;
console.log(index);
// Element.remove() 方法,把对象从它所属的 DOM 树中删除。
that.lis[index].remove();
that.sections[index].remove();
that.init();
//如果有选定状态了 呢么就不需要调用下面的点击事件 直接返回就好了
if(document.querySelector('.liactive')) return;
// 当我们删除了选定状态的li的时候 让他的前一个li赋予选定状态
index--;
//手动调用点击事件 不需要鼠标来触发
//前面为真才触发
that.lis[index]&&that.lis[index].click();
}
// 4.修改功能
editTab() {}
}
new Tab('#tab');
4.编辑功能
核心思路:双击文字的时候 在里面生成一个文本框 当失去焦点或者按下回车然后把文本框输入的值给原先元素即可。
var that;
class Tab {
constructor(id) {
that = this;
//获取元素
this.main = document.querySelector(id);
this.add = this.main.querySelector('.tabadd');
// li的父元素
// css3选择器
this.ul = this.main.querySelector('.fisrstnav ul:first-child');
this.fsection = this.main.querySelector('.tabscon');
this.init();
}
// 获取所有的li和section
updateNode() {
this.lis = this.main.querySelectorAll('li');
this.sections = this.main.querySelectorAll('section');
this.remove = this.main.querySelectorAll('.icon-guanbi');
this.spans = this.main.querySelectorAll('.fisrstnav li span:first-child');
}
// 初始化
init(){
this.updateNode();
this.add.onclick = this.addTab;
// init 初始化操作让相关元素绑定事件
for(var i =0;i<this.lis.length;i++){
// 存的是小li的索引号
this.lis[i].index = i;
this.lis[i].onclick = this.toggleTab;
this.remove[i].onclick = this.removeTab;
// 鼠标双击事件
this.spans[i].ondblclick = this.editTab;
this.sections[i].ondblclick = this.editTab;
}
}
//1.切换功能
toggleTab() {
// !!!!!一定注意this的指向问题
// console.log(this.index);
// 如果必须要清除所有样式 呢么必须使用最大的对象 也就是constructor里面的对象this
that.clearClass();
this.className = 'liactive';
// 必须用constrcutor 所以用that变量来使用另一个this this指向的lis[i]里面没有sections
that.sections[this.index].className = 'conactive';
}
clearClass() {
for(var i = 0;i<this.lis.length;i++){
this.lis[i].className = '';
this.sections[i].className = '';
}
}
//2.添加功能
addTab() {
that.clearClass();
var random = Math.random();
// alert(11); 测试用例
var li = '<li class="liactive"><span>新选项卡</span><span class="iconfont icon-guanbi"></span></li>';
var section = '<section class="conactive">测试1'+random+'</section>';
that.ul.insertAdjacentHTML('beforeend',li);
that.fsection.insertAdjacentHTML('beforeend',section);
that.init();
}
// 3.删除功能
removeTab(e) {
// 消除冒泡现象 防止触发li的点击事件
e.stopPropagation();
var index = this.parentNode.index;
console.log(index);
// Element.remove() 方法,把对象从它所属的 DOM 树中删除。
that.lis[index].remove();
that.sections[index].remove();
that.init();
//如果有选定状态了 呢么就不需要调用下面的点击事件 直接返回就好了
if(document.querySelector('.liactive')) return;
// 当我们删除了选定状态的li的时候 让他的前一个li赋予选定状态
index--;
//手动调用点击事件 不需要鼠标来触发
//前面为真才触发
that.lis[index]&&that.lis[index].click();
}
// 4.修改功能
editTab() {
// 把span里面原先的文字内容赋值给一个str变量
var str = this.innerHTML;
// 双击禁止选定文字
window.getSelection ? window.getSelection().removeAllRanges() : document.selection.empty();
// alert(11);
this.innerHTML = '<input type="text"/>'
var input = this.children[0];
input.value = str;
// 文本框里的文字处于选定状态
input.select();
// 当我们离开文本框 把值给span
// onblur失去焦点事件
input.onblur = function() {
this.parentNode.innerHTML = this.value;
}
//按下回车也可以把文本框里面的值给span
input.onkeyup = function(e) {
if(e.keyCode === 13){
this.blur();
}
}
}
}
new Tab('#tab');
注:案例所需要的html和css
链接:https://pan.baidu.com/s/1A4LmUbFEhHT6lYVrw00Zxg?pwd=1234
每天一个自我思考:面向对象和面向过程的区别是什么?评论区告诉我!!!!
下期重磅预告:js原型链 构造函数.........................