• ES6案例 ------ 模拟浏览器网页顶部切换栏【面向对象】


    -------  卡卡西最近怎么样  -------

    🧡导读 

         我们已经学会了很多 Tab 栏的写法,原生 JS 的写法,jQuery 的写法等等,学了面向对象后,我们就要学会用面向对象来实现我们 ES6 的第一个小案例------面向对象 Tab 切换栏,其中和以往不同的是,增加了添加 tab 栏,双击修改 Tab 栏等功能,其实它更像我们浏览器网页的顶部选项卡。

    -------  卡卡西最近怎么样  -------


    文章目录:

    一:模拟浏览器网页效果 

     二:功能实现剖析

    2.1 创建类并实例化对象

    2.2 获取标签与绑定事件

    2.3 清除样式函数

    2.4 切换选项卡

    2.5 增加选项卡

    2.6 删除选项卡

    2.7 修改选项卡内容

      三:完整代码

    html代码

    css 代码

    Java Script 代码


    一:模拟浏览器网页效果 

    切换效果:点击tab栏可切换

    添加效果:点击右侧加号可以新增一个栏目

    删除效果: 点击选项卡里右侧的叉号可以将该对应选项卡删除

    修改内容: 双击选项卡内容或下方文本内容均可以修改内容


     二:功能实现剖析

    本案例使用了面向对象,所有的功能均封装在了类内的函数中

    2.1 创建类并实例化对象

    • 首先创建类,构造函数的传参为我们模拟浏览器的最外层大盒子的类名:.out-box,后续获取到任何内容,标签,都是通过这个传进来的类名来进阶获取,例如或许获取的 li,section,ul 等等
    1. class Tab{
    2. constructor(classname){}
    3. }
    4. new Tab('.out-box')

    2.2 获取标签与绑定事件

    • 我们注意到为什么除了构造函数里获取的元素,还单独写了个函数来获取呢,这是因为我们有删除与添加tab选项卡的功能,如果我们只在构造函数里写了一次的话,就会导致添加或删除选项卡后出现不可预知的错误,这个函数内只获取 li,section,remove,span文本等对应了增加删除等这些时刻在变化的标签
    • init函数内为绑定元素,循环绑定了点击切换选项卡事件,双击修改选项卡事件 (dblclick)等等
    • 一定要注意 this 的指向问题,constructor中的this指向的是实例化对象,函数中的this指向的是函数的调用者
    • 还需要注意绑定事件时不要给函数加括号,否则会不经过事件触发直接调用
    • 在遍历的过程中,会给 i 添加一个 index 属性
    1. constructor(classname){
    2. that=this;
    3. this.main=document.querySelector(classname);
    4. this.add=this.main.querySelector('.banner-add');
    5. this.banner_ul=this.main.querySelector('.banner-ul');
    6. this.text_box=this.main.querySelector('.text-box');
    7. this.init();
    8. }
    9. //获取li与section
    10. update_Nodes(){
    11. this.lis=this.main.querySelectorAll('li');
    12. this.sections=this.main.querySelectorAll('section');
    13. this.remove=this.main.querySelectorAll('.banner-close');
    14. this.spans=this.main.querySelectorAll('.neirong');
    15. }
    16. //初始化
    17. init(){
    18. this.update_Nodes();
    19. for(var i=0;i<this.lis.length;i++){
    20. this.lis[i].index=i;
    21. this.lis[i].addEventListener('click',this.toggletab);
    22. this.remove[i].addEventListener('click',this.closetab);
    23. this.spans[i].addEventListener('dblclick',this.changetab_span);
    24. this.sections[i].addEventListener('dblclick',this.changetab_section);
    25. }
    26. this.add.addEventListener('click',this.addtab);
    27. }

    2.3 清除样式函数

    • 由于我们在执行过程中必定要多次运用排他思想来清除样式,所以我们可以将清除的代码单独封装到一个清除函数中
    • 此处的this指向的是函数调用者
    • 实现过程如下:遍历获取到的所有的 li ,然后清除每个 li 和 section 的类名
    1. clearclass(){
    2. for(var i=0;i<this.lis.length;i++){
    3. this.lis[i].className='';
    4. this.sections[i].className='';
    5. }
    6. }

    2.4 切换选项卡

    • that 代表的是构造函数里的 this,指向实例化的对象
    • 此处的 this 指向的是切换函数的调用者,即绑定事件时的每一个被点击的 li,所以这个this 指向的是被触发的 li,及被触发的选项卡,于是给这个 this 添加类名,给 section 也同样添加类名(此类名内容为让其 display 变为 block 显示,默认为 none 隐藏)
    • 需要注意的是 section 为什么是 that,不是 this 呢,因为此处的 this 代表 li,而我们需要的是构造函数内的 this,所以此处使用 that
    1. toggletab(){
    2. that.clearclass();
    3. this.className='li-current'
    4. that.sections[this.index].className='section-current'
    5. }

    2.5 增加选项卡

    • 我们拓展个增加元素的知识点:insertAdjacentHTML(),内部参数有 beforebegin(在父元素的前面添加),afterbegin(在父元素内部第一个添加),beforeend(在父元素内部最后一个位置添加),afterend(在父元素后面添加),最主要的是,这个方法可以直接添加字符串
    • 实现过程我们先创建了两个元素,li 与 section,并添加了类名(因为想要新创建的选项卡直接显示),然后再使用上述该方法添加即可
    • 对于最后又调用了一次 init 方法,我想大家就可以理解了,因为我们创建了元素之后,调用 init 可以重新获取以便我们的元素,重新再分别绑定各个事件,保证不会出错
    1. addtab(){
    2. that.clearclass();
    3. var li='<li class="li-current"><span class="neirong">新页面</span><span class="banner-close">×</span></li>';
    4. var text='<section class="section-current">新内容</section>'
    5. that.banner_ul.insertAdjacentHTML('beforeend',li);
    6. that.text_box.insertAdjacentHTML('beforeend',text);
    7. that.init();
    8. }

    2.6 删除选项卡

    • 由于我们的删除按钮在选项卡里面,所以我们点击叉号后会自发冒泡,冒泡到 li 时由于其也绑定了事件,会触发其显示,为了解决这一问题我们先解除冒泡 stopPropagation()
    • 叉号没有 index 值,但是它父亲有啊,我们就把其对应的叉号拿到其父亲的 index,然后把这个索引值对应的 li 与 section 删除掉,删除自身我们可以使用 remove()
    • 为了让关闭后让前一个元素显示,我们删除后让 index-- 然后让自减后 index 对应的 li 添加一个自动点击事件 click()
    • 最后再调用 init 方法重新获取绑定元素事件
    1. closetab(event){
    2. event.stopPropagation()
    3. var index=this.parentNode.index;
    4. that.lis[index].remove();
    5. that.sections[index].remove();
    6. index--;
    7. that.lis[index] && that.lis[index].click()
    8. that.init();
    9. }

    2.7 修改选项卡内容

    • 修改的大致思路为:现将其原本内容拿来赋值给 str 变量,双击后将其 li 的内容改为一个输入框,输入框内容替换为 str 存放的内容,再调用方法 select(),让其输入框的内容全选起来,使用户输入任何内容都可以将原本内容替换掉
    • 然后给 输入框绑定失焦的方法,失焦后将输入框的内容替换为文本即可
    1. //tab_span修改
    2. changetab_span(){
    3. var str=this.innerHTML;
    4. this.innerHTML='<input type="text" class="span-ipt">'
    5. var input= this.children[0];
    6. input.value=str;
    7. input.select();
    8. input.addEventListener('blur',function(){
    9. this.parentNode.innerHTML=this.value;
    10. })
    11. input.addEventListener('keydown',function(event){
    12. if(event.keyCode==13){
    13. this.blur();
    14. }
    15. })
    16. }
    17. //tab_section修改
    18. changetab_section(){
    19. var str=this.innerHTML;
    20. this.innerHTML='<input type="text" class="section-ipt">'
    21. var input= this.children[0];
    22. input.value=str;
    23. input.select();
    24. input.addEventListener('blur',function(){
    25. this.parentNode.innerHTML=this.value;
    26. })
    27. input.addEventListener('keydown',function(event){
    28. if(event.keyCode==13){
    29. this.blur();
    30. }
    31. })
    32. }

      三:完整代码

    html代码:

    1. <!DOCTYPE html>
    2. <html lang="en">
    3. <head>
    4. <meta charset="UTF-8">
    5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
    6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
    7. <title>tab栏切换案例</title>
    8. <link rel="stylesheet" href="./tab切换.css">
    9. </head>
    10. <body>
    11. <div class="out-box">
    12. <div class="banner-box">
    13. <div class="banner-left">
    14. <img src="./img/积分说明.png" alt="说明" title="说明" class="banner-img-say">
    15. </div>
    16. <ul class="banner-ul">
    17. <li class="li-current"><span class="neirong">内容一</span><span class="banner-close">×</span></li>
    18. <li ><span class="neirong">内容二</span><span class="banner-close">×</span></li>
    19. <li ><span class="neirong">内容三</span><span class="banner-close">×</span></li>
    20. </ul>
    21. <div class="banner-add">+</div>
    22. </div>
    23. <div class="src-box">
    24. <img src="./img/首页.png" alt="主菜单" title="主菜单" class="src-img-home">
    25. <img src="./img/更多.png" alt="更多" title="更多" class="src-img-more">
    26. <input type="text" class="src" placeholder="✪ 文件 | file:///C:/Users/HUAWEI/Desktop/demo/tab.html" >
    27. </div>
    28. <div class="text-box">
    29. <section class="section-current">内容一</section>
    30. <section >内容二</section>
    31. <section >内容三</section>
    32. </div>
    33. </div>
    34. <script src="./tab切换.js"></script>
    35. </body>
    36. </html>

    css 代码:

    1. *{
    2. margin: 0;
    3. padding: 0;
    4. }
    5. body{
    6. background-color: rgb(104, 104, 104);
    7. }
    8. .out-box{
    9. box-sizing: border-box;
    10. width: 1200px;
    11. height: 750px;
    12. border:1px solid black;
    13. margin: 40px auto;
    14. background-color: rgb(251, 251, 251);
    15. box-shadow: 0 0 6px 2px rgb(220, 220, 220) inset;
    16. }
    17. .banner-box{
    18. width: 1198px;
    19. height: 40px;
    20. border-bottom: 1px solid black;
    21. background-color: rgb(218, 218, 218);
    22. }
    23. .banner-left{
    24. float: left;
    25. box-sizing: border-box;
    26. position: relative;
    27. width: 50px;
    28. height: 40px;
    29. background-color: rgb(191, 191, 191);
    30. box-shadow: -3px 0 6px 1px rgb(171, 171, 171) inset;
    31. border-top-right-radius: 5px;
    32. border-bottom-right-radius: 5px;
    33. border-right: 1px solid black;
    34. }
    35. .banner-img-say{
    36. box-sizing: border-box;
    37. position: absolute;
    38. float: left;
    39. top: 10px;
    40. left: 14px;
    41. width: 20px;
    42. height: 20px;
    43. }
    44. .banner-ul{
    45. position: relative;
    46. float: left;
    47. box-sizing: border-box;
    48. }
    49. li{
    50. box-sizing: border-box;
    51. float: left;
    52. width: 150px;
    53. height: 40px;
    54. border-right: 1px solid black;
    55. list-style: none;
    56. border-top-right-radius: 6px;
    57. border-bottom-right-radius: 6px;
    58. border-bottom: 5px solid rgb(150, 150, 150);
    59. position: relative;
    60. cursor: pointer;
    61. }
    62. .li-current{
    63. background-color: rgb(255, 255, 255);
    64. border-bottom: 5px solid rgb(255, 201, 52);
    65. }
    66. .neirong{
    67. float: left;
    68. box-sizing: border-box;
    69. width: 100px;
    70. height: 35px;
    71. line-height: 35px;
    72. padding-left: 10px;
    73. font-size: 14px;
    74. }
    75. .banner-close{
    76. box-sizing: border-box;
    77. float:right;
    78. width: 20px;
    79. height: 20px;
    80. line-height: 20px;
    81. text-align: center;
    82. margin-top: 8px;
    83. margin-right: 5px;
    84. cursor: pointer;
    85. font-size: 19px;
    86. padding-left: 1px;
    87. color: rgb(85, 85, 85);
    88. }
    89. .banner-close:hover{
    90. background-color: rgb(242, 242, 242);
    91. }
    92. .banner-add{
    93. box-sizing: border-box;
    94. float: left;
    95. width: 40px;
    96. height: 40px;
    97. padding-left: 9px;
    98. line-height: 38px;
    99. font-size: 30px;
    100. color: rgb(98, 98, 98);
    101. cursor: pointer;
    102. }
    103. .banner-add:hover{
    104. background-color: rgb(237, 237, 237);
    105. }
    106. .src-box{
    107. box-sizing: border-box;
    108. position: relative;
    109. width: 1198px;
    110. height: 30px;
    111. border-bottom: 1px solid black;
    112. background-color: rgb(239, 239, 239);
    113. }
    114. .src-img-home{
    115. box-sizing: border-box;
    116. width: 20px;
    117. height: 20px;
    118. position: absolute;
    119. top: 4.1px;
    120. left:22px;
    121. }
    122. .src-img-more{
    123. box-sizing: border-box;
    124. width: 35px;
    125. height: 25px;
    126. position: absolute;
    127. top: 3.5px;
    128. right:12px;
    129. }
    130. .src{
    131. box-sizing: border-box;
    132. position: absolute;
    133. top: 3px;
    134. left: 60px;
    135. width: 500px;
    136. height: 23px;
    137. outline: none;
    138. background-color: rgb(255, 255, 255);
    139. border: 1px solid black;
    140. border-radius: 5px;
    141. line-height: 35px;
    142. padding-left: 10px;
    143. color:rgb(105, 105, 105)
    144. }
    145. .text-box{
    146. box-sizing: border-box;
    147. margin: 12.5px auto;
    148. width: 98%;
    149. height: 87%;
    150. background-color: rgb(212, 212, 212);
    151. }
    152. section{
    153. box-sizing: border-box;
    154. width: 100%;
    155. height: 100%;
    156. border:1px solid rgb(26, 26, 26);
    157. background-color: rgb(225, 225, 225);
    158. display: none;
    159. }
    160. .section-current{
    161. display: block;
    162. }
    163. .span-ipt{
    164. width: 100px;
    165. height: 23px;
    166. outline: none;
    167. }
    168. .section-ipt{
    169. margin: 5px;
    170. width: 200px;
    171. height: 30px;
    172. outline: none;
    173. }

    Java Script 代码:

    1. document.addEventListener('DOMContentLoaded',function(){
    2. document.addEventListener('selectstart',function(event){
    3. event.preventDefault()
    4. })
    5. document.addEventListener('contextmenu',function(event){
    6. event.preventDefault()
    7. })
    8. var that;
    9. class Tab{
    10. constructor(classname){
    11. that=this;
    12. this.main=document.querySelector(classname);
    13. this.add=this.main.querySelector('.banner-add');
    14. this.banner_ul=this.main.querySelector('.banner-ul');
    15. this.text_box=this.main.querySelector('.text-box');
    16. this.init();
    17. }
    18. //获取li与section
    19. update_Nodes(){
    20. this.lis=this.main.querySelectorAll('li');
    21. this.sections=this.main.querySelectorAll('section');
    22. this.remove=this.main.querySelectorAll('.banner-close');
    23. this.spans=this.main.querySelectorAll('.neirong');
    24. }
    25. //初始化
    26. init(){
    27. this.update_Nodes();
    28. for(var i=0;i<this.lis.length;i++){
    29. this.lis[i].index=i;
    30. this.lis[i].addEventListener('click',this.toggletab);
    31. this.remove[i].addEventListener('click',this.closetab);
    32. this.spans[i].addEventListener('dblclick',this.changetab_span);
    33. this.sections[i].addEventListener('dblclick',this.changetab_section);
    34. }
    35. this.add.addEventListener('click',this.addtab);
    36. }
    37. //tab切换
    38. toggletab(){
    39. that.clearclass();
    40. this.className='li-current'
    41. that.sections[this.index].className='section-current'
    42. }
    43. //排他清除
    44. clearclass(){
    45. for(var i=0;i<this.lis.length;i++){
    46. this.lis[i].className='';
    47. this.sections[i].className='';
    48. }
    49. }
    50. //tab关闭
    51. closetab(event){
    52. event.stopPropagation()
    53. var index=this.parentNode.index;
    54. that.lis[index].remove();
    55. that.sections[index].remove();
    56. index--;
    57. that.lis[index] && that.lis[index].click()
    58. that.init();
    59. }
    60. //tab添加
    61. addtab(){
    62. that.clearclass();
    63. var li='<li class="li-current"><span class="neirong">新页面</span><span class="banner-close">×</span></li>';
    64. var text='<section class="section-current">新内容</section>'
    65. that.banner_ul.insertAdjacentHTML('beforeend',li);
    66. that.text_box.insertAdjacentHTML('beforeend',text);
    67. that.init();
    68. }
    69. //tab_span修改
    70. changetab_span(){
    71. var str=this.innerHTML;
    72. this.innerHTML='<input type="text" class="span-ipt">'
    73. var input= this.children[0];
    74. input.value=str;
    75. input.select();
    76. input.addEventListener('blur',function(){
    77. this.parentNode.innerHTML=this.value;
    78. })
    79. input.addEventListener('keydown',function(event){
    80. if(event.keyCode==13){
    81. this.blur();
    82. }
    83. })
    84. }
    85. //tab_section修改
    86. changetab_section(){
    87. var str=this.innerHTML;
    88. this.innerHTML='<input type="text" class="section-ipt">'
    89. var input= this.children[0];
    90. input.value=str;
    91. input.select();
    92. input.addEventListener('blur',function(){
    93. this.parentNode.innerHTML=this.value;
    94. })
    95. input.addEventListener('keydown',function(event){
    96. if(event.keyCode==13){
    97. this.blur();
    98. }
    99. })
    100. }
    101. }
    102. new Tab('.out-box')
    103. })

  • 相关阅读:
    Linux platform总线驱动基础知识
    Spring让人眼前一亮的11个小技巧
    《痞子衡嵌入式半月刊》 第 100 期
    深入理解JavaScript——执行上下文与调用栈
    01准备阶段 Latex相关软件安装
    React是什么?
    分布式事务
    Vuex使用方式及异步问题处理
    【视频】马尔可夫链原理可视化解释与R语言区制转换MRS实例|数据分享
    什么是代理IP
  • 原文地址:https://blog.csdn.net/weixin_52212950/article/details/125349004