Blogger Information
Blog 21
fans 0
comment 0
visits 10032
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
实战1: 经典选项卡- 优化
放手去爱
Original
330 people have browsed it

实战1: 经典选项卡- 优化

  1. <!DOCTYPE html>
  2. <html lang="zh-CN">
  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>实战1: 经典选项卡- 优化</title>
  8. <style>
  9. /* 隐藏 */
  10. .hidden {
  11. display: none;
  12. }
  13. /* 显示 */
  14. .active {
  15. display: block;
  16. }
  17. .type > *.active,
  18. .content > *.active {
  19. background-color: lightgreen;
  20. }
  21. </style>
  22. </head>
  23. <body>
  24. <div class="box">
  25. <!-- 1. 栏目组 -->
  26. <div class="type" style="display: flex"></div>
  27. <!-- 2. 内容组 -->
  28. <div class="content"></div>
  29. </div>
  30. <script type="module">
  31. // 导入模块
  32. import * as tabs from './modules/tabs.js';
  33. // 1. 获取栏目,内容容器元素
  34. const type = document.querySelector('.type');
  35. const content = document.querySelector('.content');
  36. // 2. 页面加载完成,创建栏目和对应的内容
  37. // 自动生成栏目和内容数据
  38. window.onload = () => tabs.createTab(type, content);
  39. // 3. 点击栏目时,设置按钮的状态,与按钮对应的内容的状态
  40. // 事件委托(事件冒泡)
  41. type.onclick = ev => {
  42. // 因为存在事件委托,就需要区分不同的事件主体
  43. // 事件主体有二个: 事件绑定主体, 事件触发主体
  44. // 绑定主体
  45. // ev.currentTarget
  46. // 触发主体
  47. // ev.target
  48. // 绑定主体, 是触发主体父级元素
  49. // 1. 当前按钮高亮
  50. tabs.setBtnStatus(ev);
  51. // 2. 与按钮对应的内容显示出来
  52. // ev.target: 当前按钮
  53. tabs.setContentStatus(ev, ev.target);
  54. };
  55. </script>
  56. </body>
  57. </html>

JStabs.js

  1. // todo 选项卡的数据以及方法
  2. // * 栏目数据
  3. const cates = [
  4. { cid: 1, cname: '国际新闻' },
  5. { cid: 2, cname: '中国新闻' },
  6. { cid: 3, cname: '安徽新闻' },
  7. ];
  8. // * 列表数据
  9. // 列表数据,必须与指定的栏目,一一对应
  10. const details = [
  11. {
  12. key: 1,
  13. cid: 1,
  14. content: [
  15. {
  16. title: '俄罗斯宣布从赫尔松部分地区撤军',
  17. url: 'https://news.ifeng.com/c/8KoK54urn1k',
  18. },
  19. {
  20. title: '俄罗斯宣布从赫尔松部分地区撤军',
  21. url: 'https://news.ifeng.com/c/8KoK54urn1k',
  22. },
  23. {
  24. title: '俄罗斯宣布从赫尔松部分地区撤军',
  25. url: 'https://news.ifeng.com/c/8KoK54urn1k',
  26. },
  27. ],
  28. },
  29. {
  30. key: 2,
  31. cid: 2,
  32. content: [
  33. {
  34. title: '空战隐身无人僚机亮相!',
  35. url: 'https://news.ifeng.com/c/8KoeDFJXF1b',
  36. },
  37. {
  38. title: '空战隐身无人僚机亮相!',
  39. url: 'https://news.ifeng.com/c/8KoeDFJXF1b',
  40. },
  41. {
  42. title: '空战隐身无人僚机亮相!',
  43. url: 'https://news.ifeng.com/c/8KoeDFJXF1b',
  44. },
  45. ],
  46. },
  47. {
  48. key: 3,
  49. cid: 3,
  50. content: [
  51. {
  52. title: '安康码”上新!家庭成员核酸情况查询更便捷',
  53. url: 'https://ah.ifeng.com/c/8KkGUDhAZNZ',
  54. },
  55. {
  56. title: '安康码”上新!家庭成员核酸情况查询更便捷',
  57. url: 'https://ah.ifeng.com/c/8KkGUDhAZNZ',
  58. },
  59. {
  60. title: '安康码”上新!家庭成员核酸情况查询更便捷',
  61. url: 'https://ah.ifeng.com/c/8KkGUDhAZNZ',
  62. },
  63. ],
  64. },
  65. ];
  66. // 创建样目和对应的内容区
  67. function createTab(type, content) {
  68. // 1. 生成样目
  69. for (let i = 0; i < cates.length; i++) {
  70. // (1) 创建一个按钮
  71. const btn = document.createElement('button');
  72. // (2) 设置按钮的文本
  73. btn.textContent = cates[i].cname;
  74. // (3) 给按钮添加一个自定义 data-key, 主要是为了一内容id绑定
  75. btn.dataset.key = cates[i].cid;
  76. // (4) 默认高亮第1个,所以第一个加上class="active"
  77. if (i === 0) btn.classList.add('active');
  78. // (5) 将新按钮, 添加到栏目容器元素中 type
  79. type.append(btn);
  80. }
  81. // 2. 生成内容
  82. for (let i = 0; i < details.length; i++) {
  83. // (1) 创建列表 <ul>
  84. const ul = document.createElement('ul');
  85. // (2) 添加列表索引<ul data-key>
  86. ul.dataset.key = details[i].cid;
  87. // (3) 默认显示第1个,其它隐藏
  88. ul.classList.add(i === 0 ? 'active' : 'hidden');
  89. // (4) 生成子元素<li><a>用于显示每一条数据
  90. for (let k = 0; k < details[i].content.length; k++) {
  91. // 1. 生成 <li>
  92. const li = document.createElement('li');
  93. // 2. 生成 <a>
  94. const a = document.createElement('a');
  95. // 3. a.href
  96. a.href = details[i].content[k].url;
  97. // 4. a.textContent
  98. a.textContent = details[i].content[k].title;
  99. // 5. 将<a>添加到<li>
  100. li.append(a);
  101. // 6. <li>添加到<ul>
  102. ul.append(li);
  103. // 7. <ul>添加到内容容器中.content
  104. content.append(ul);
  105. }
  106. }
  107. }
  108. // 设置按钮高亮
  109. function setBtnStatus(ev) {
  110. // 1. 当前按钮
  111. const currentBtn = ev.target;
  112. // 2. 去掉所有按钮的active, 遍历
  113. // ev.currentTarget: 事件绑定主体 , 父元素
  114. [...ev.currentTarget.children].forEach(btn => btn.classList.remove('active'));
  115. // 3. 设置当前按钮高亮
  116. currentBtn.classList.add('active');
  117. }
  118. // 设置内容状态: 与按钮对应的内容显示出来
  119. function setContentStatus(ev, currentBtn) {
  120. // 1. 获取所有列表
  121. const lists = document.querySelectorAll('.content > ul');
  122. // 2. 去掉所有列表active,换成hidden
  123. lists.forEach(list => list.classList.replace('active', 'hidden'));
  124. // 3. 找到与栏目key对应的列表
  125. // lists: NodeList对象, 不是数组
  126. const currentList = [...lists].find(list => list.dataset.key == currentBtn.dataset.key);
  127. // 返回当前应该高亮显示的列表
  128. // 4. 将要显示的列表,加上active,显示出来
  129. currentList.classList.replace('hidden', 'active');
  130. }
  131. export { createTab, setBtnStatus, setContentStatus };
Correcting teacher:PHPzPHPz

Correction status:qualified

Teacher's comments:完成的不错, 下次可以把示例效果图也贴出来
Statement of this Website
The copyright of this blog article belongs to the blogger. Please specify the address when reprinting! If there is any infringement or violation of the law, please contact admin@php.cn Report processing!
All comments Speak rationally on civilized internet, please comply with News Comment Service Agreement
0 comments
Author's latest blog post