赞
踩
<main> <h4> Js 面向对象 动态添加标签页 </h4> <div class="tabsbox" id="tab"> <!-- tab 标签 --> <nav class="fisrstnav"> <ul> <li class="liactive"><span>测试1</span><span class="iconfont icon-guanbi"></span></li> <li><span>测试2</span><span class="iconfont icon-guanbi"></span></li> <li><span>测试3</span><span class="iconfont icon-guanbi"></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>
* { margin: 0; padding: 0; } ul li { list-style: none; } main { width: 960px; height: 500px; border-radius: 10px; margin: 50px auto; } main h4 { height: 100px; line-height: 100px; text-align: center; } .tabsbox { width: 900px; margin: 0 auto; height: 400px; border: 1px solid lightsalmon; position: relative; } nav ul { overflow: hidden; } nav ul li { float: left; width: 100px; height: 50px; line-height: 50px; text-align: center; border-right: 1px solid #ccc; position: relative; } nav ul li.liactive { border-bottom: 2px solid #fff; z-index: 9; } #tab input { width: 80%; height: 60%; } nav ul li span:last-child { position: absolute; user-select: none; font-size: 12px; top: 0px; right: 0; display: inline-block; width: 20px; height: 20px; background-color: red; cursor: pointer; } .tabadd { position: absolute; /* width: 100px; */ top: 0; right: 0; } .tabadd span { display: block; width: 20px; height: 20px; line-height: 20px; text-align: center; border: 1px solid #ccc; float: right; margin: 10px; user-select: none; cursor: pointer; } .tabscon { width: 100%; height: 300px; position: absolute; padding: 30px; top: 50px; left: 0px; box-sizing: border-box; border-top: 1px solid #ccc; } .tabscon section, .tabscon section.conactive { display: none; width: 100%; height: 100%; } .tabscon section.conactive { display: block; }
<script type="text/javascript"> //定义一个that变量,让实例对象中的this进行赋值 var that; class Tab{ constructor(id){ //将实力对象中的this赋值到that中 that = this; //首先获取最大父盒子的元素 , 此处的this指向实力对象 //获取需要操作的标签 this.main = document.querySelector(id); // //获取最大父盒子中的所有li // this.lis = this.main.querySelectorAll('li'); // // 获取最大父盒子中的所有section // this.sections = this.main.querySelectorAll('section'); /*动态创建li和section 可以将选择器更换为*/ // //获取最大父盒子中的所有li // this.lis = this.main.getElementsByTagName('li'); // // 获取最大父盒子中的所有section // this.sections = this.main.getElementsByTagName('section'); // 因为getElementsByTagName具有隐式遍历的作用 //获取最大父盒子中的tabadd this.add = this.main.querySelector('.tabadd'); //获取最大父盒子中的fisrstnav下的第一个元素标签 (li的父元素) this.ul = this.main.querySelector('.fisrstnav ul:first-child'); //获取最大父盒子中的tabscon的元素标签 (tabscon父元素) this.fsection = this.main.querySelector('.tabscon'); // //获取最大盒子中的icon-guanbi // this.remove = this.main.querySelectorAll('.icon-guanbi') this.init(); } //设置一个初始化的函数,让相关元素绑定事件(主要就是添加相关的绑定事件) init(){ //一初始化的时候就调用新的li和section(重新调用切记写在最前面,要不然添加时,最后一个li没有效果) this.updateNode(); //循环li,进行添加绑定事件,此处的长度设置为实例对象中的写法//this.lis.length for (var i = 0; i < this.lis.length; i++) { // 此处为了后期与section进行绑定,利用实力对象形式设置一个变量保存每次遍历的索引 this.lis[i].index = i; //会给每个li设置点击事件 //此处测试li是否已经可以点击,拿到索引号 // this.lis[i].onclick = function(){ // console.log(this.index); // } //每个li设置点击事件,触发toggleTab的函数效果 this.lis[i].onclick = this.toggleTab; //给每个icon-guanbi按钮进行绑定事件 this.remove[i].onclick = this.removeTab; //给每个span设置鼠标双击事件 this.spans[i].ondblclick = this.editTab; //给每个sections绑定一个双击事件(此处因为所需要用到的方法跟span设置的事件方法一样,所以此处直接调用span的双击方法) this.sections[i].ondblclick = this.editTab; } //添加事件不需要进行遍历 this.add.onclick = this.addTab; } //重新获取所有的小li和section updateNode(){ //获取最大父盒子中的所有li this.lis = this.main.querySelectorAll('li'); // 获取最大父盒子中的所有section this.sections = this.main.querySelectorAll('section'); //获取最大盒子中的icon-guanbi this.remove = this.main.querySelectorAll('.icon-guanbi') //获取所有的li下的第一个span this.spans = this.main.querySelectorAll('.fisrstnav li span:first-child') } /*****************************************************************************************************/ //1.切换功能 toggleTab(){ //在此处调用清楚样式的函数,此处的this修改为that,因为this的话只能理解为li调用了此方法 //其中还有sections的存在,因此用that进行包含 that.clearClass(); //测试li是否已经可以点击,拿到索引号 // console.log(this.index); //此处的this指向的是li这个标签(谁调用了我,我就指向谁) this.className = 'liactive'; //因为this指向的是li,li中没有conactive这个类名属性,所以this.sections[thsi.index] = 'conactive'; // 不管用,因此可以得到此conactive为constructor(实例对象)中的元素 // this.sections[thsi.index] = 'conactive'; //设置一个全局变量taht,对实例对象中的this进行赋值,进行调用 //因此此处的this,修改为that that.sections[this.index].className = 'conactive'; } //设置一个清楚样式的函数(清除所有li和section中的类) clearClass(){ for (let i = 0; i < this.lis.length; i++) { //清除li和sections下的所有类(此处用到排他思想处理) this.lis[i].className = ''; //此处sections可以用that或者this,在调用方法时用that就可以了 that.sections[i].className = ''; } } /*****************************************************************************************************/ //2.添加功能 addTab(){ //进行排他思想,让创建的标签类达到比较好的效果 that.clearClass(); //绑定测试 // alert(123) //为了生成的效果好看,添加个生成随机数 var random = Math.random(); //(1) 创建li元素和section元素 var li = '<li class="liactive"><span>新选项卡</span><span class="iconfont icon-guanbi"></span></li>' var section = ' <section class="conactive">新内容'+ random +'</section>'; //(2) 将以下的两个元素添加到父元素中(利用insertAdjacentHTML方法进行子元素的添加,因为insertAdjacentHTML不局限于文字添加,方法中的beforeend,是将标签等信息放在盒子里面的最后一个) //因为addTab指向的实例对对象,因此此处用that that.ul.insertAdjacentHTML('beforeend',li); that.fsection.insertAdjacentHTML('beforeend',section); //此处在重新调用一次init方法; that.init(); } // 已经设置了 updateNode() 函数重新调用li和section的个数 /*****************************************************************************************************/ //3.删除功能 //给当前函数添加事件对象(事件参数),阻止事件冒泡行为 removeTab(e){ e.stopPropagation(); //利用事件参数阻止冒泡,防止出发li的点击事件 //此时会出现新增li中的删除按钮跟当前索引取不到一起,因此将获取关闭按钮的元素放到 updateNode()方法中重新获取即可 //引用父元素的索引号 var index = this.parentNode.index; // 测试 console.log(index); // remove() 方法则可以直接删除指定的元素 that.lis[index].remove(); that.sections[index].remove(); //此处调用init方法,为了让init方法执行 updateNode() 方法,即可拿到新的元素进行遍历使用 that.init(); //当我们删除的不是选中状态的li的时候,原来的选中状态li保持不变 //如果当前的标签存折liactive这个标签状态,就直接返回值,不必执行下面的代码 if(document.querySelector('.liactive'))return; //当我们删除了选中状态的这个li的时候,让它的前一个li处于选定状态 //让index--;从而让前一个li为选中状态 index--; //index--;于此同时自动调用lis的点击事件,让sections也属于选中状态 // that.lis[index].click(); //利用 && 对前后的效果进行判断 (&& 与) that.lis[index] && that.lis[index].click(); } /*****************************************************************************************************/ //4.修改功能 editTab(){ //先获取原来的文本文字 var str = this.innerHTML; //双击禁止选定文字; window.getSelection ? window.getSelection().removeAllRanges() : document.selection.empty() //测试 // alert(123) //使鼠标双击到的标签设置为文本标签 this.innerHTML = '<input type="text" />'; //获取input标签,将原来的文本文字赋值给input var input = this.children[0]; input.value = str; //让文本框内的文字处于选定状态 input.select(); //当我们离开文本框,将文本框内的值设置给span input.onblur = function(){ this.parentNode.innerHTML = this.value; }; input.onkeyup = function(e){ if(e.keyCode === 13){ //手动调用表单失去焦点事件 不需要鼠标离开操作 this.blur(); } } } } //创建的实力对象必须存在实例函数的下面,不然执行结果为undeiful //首先过去最大的父盒子元素 /*var a = */ new Tab('#tab'); // a.init(); </script>
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。