飞道的博客

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

517人阅读  评论(0)

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

🧡导读 

     我们已经学会了很多 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. })


转载:https://blog.csdn.net/weixin_52212950/article/details/125349004
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场