Blogger Information
Blog 41
fans 0
comment 0
visits 31218
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
JS原生实现选项卡和图片懒加载
陈强
Original
570 people have browsed it

选项卡

  1. //css样式
  2. <style>
  3. * {
  4. margin: 0;
  5. padding: 0;
  6. box-sizing: border-box;
  7. }
  8. a {
  9. text-decoration: none;
  10. color: #333;
  11. }
  12. ul li {
  13. list-style: none;
  14. }
  15. .con {
  16. width: 20em;
  17. box-shadow: 0 0 3px #ccc;
  18. margin: 2em;
  19. }
  20. .con .tab {
  21. display: grid;
  22. grid-template-columns: repeat(3, 1fr);
  23. text-align: center;
  24. background-color: #ccc;
  25. }
  26. .con .tab li {
  27. padding: 0.5em 0;
  28. cursor: pointer;
  29. }
  30. .con .active {
  31. background-color: #fff;
  32. }
  33. .con .item {
  34. padding: 0.5em;
  35. }
  36. .con .item li {
  37. padding: 0.2em 0;
  38. }
  39. .item {
  40. padding: 20px;
  41. display: none;
  42. }
  43. .item.active {
  44. display: block;
  45. }
  46. </style>
  47. //html代码
  48. <div class="con">
  49. <ul class="tab">
  50. <li class="active" data-index="1">第一个</li>
  51. <li data-index="2">第二个</li>
  52. <li data-index="3">第三个</li>
  53. </ul>
  54. <ul data-index="1" class="item active">
  55. <li><a href="#">第一个选项卡内容</a></li>
  56. <li><a href="#">第一个选项卡内容</a></li>
  57. <li><a href="#">第一个选项卡内容</a></li>
  58. <li><a href="#">第一个选项卡内容</a></li>
  59. <li><a href="#">第一个选项卡内容</a></li>
  60. <li><a href="#">第一个选项卡内容</a></li>
  61. <li><a href="#">第一个选项卡内容</a></li>
  62. <li><a href="#">第一个选项卡内容</a></li>
  63. <li><a href="#">第一个选项卡内容</a></li>
  64. <li><a href="#">第一个选项卡内容</a></li>
  65. </ul>
  66. <ul data-index="2" class="item">
  67. <li><a href="#">第二个选项卡内容</a></li>
  68. <li><a href="#">第二个选项卡内容</a></li>
  69. <li><a href="#">第二个选项卡内容</a></li>
  70. <li><a href="#">第二个选项卡内容</a></li>
  71. <li><a href="#">第二个选项卡内容</a></li>
  72. <li><a href="#">第二个选项卡内容</a></li>
  73. <li><a href="#">第二个选项卡内容</a></li>
  74. <li><a href="#">第二个选项卡内容</a></li>
  75. <li><a href="#">第二个选项卡内容</a></li>
  76. <li><a href="#">第二个选项卡内容</a></li>
  77. </ul>
  78. <ul data-index="3" class="item">
  79. <li><a href="#">第三个选项卡内容</a></li>
  80. <li><a href="#">第三个选项卡内容</a></li>
  81. <li><a href="#">第三个选项卡内容</a></li>
  82. <li><a href="#">第三个选项卡内容</a></li>
  83. <li><a href="#">第三个选项卡内容</a></li>
  84. <li><a href="#">第三个选项卡内容</a></li>
  85. <li><a href="#">第三个选项卡内容</a></li>
  86. <li><a href="#">第三个选项卡内容</a></li>
  87. <li><a href="#">第三个选项卡内容</a></li>
  88. <li><a href="#">第三个选项卡内容</a></li>
  89. </ul>
  90. </div>
  91. //js代码
  92. <script>
  93. const tab = document.querySelector(".con .tab");
  94. const items = document.querySelectorAll(".con .item");
  95. tab.onmouseover = (ev) => {
  96. [...tab.children].forEach((item) => item.classList.remove("active"));
  97. console.log([Array.from(tab.children)]);
  98. ev.target.classList.add("active");
  99. items.forEach((item) => item.classList.remove("active"));
  100. [...items].filter((item) => item.dataset.index === ev.target.dataset.index)[0].classList.add("active");
  101. };
  102. </script>

图片懒加载

  1. //html代码
  2. <ul class="imgs">
  3. <img src="images/temp.jpg" alt="" data-src="images/img-1.jpg" />
  4. <img src="images/temp.jpg" alt="" data-src="images/img-2.jpg" />
  5. <img src="images/temp.jpg" alt="" data-src="images/img-3.jpg" />
  6. <img src="images/temp.jpg" alt="" data-src="images/img-4.jpg" />
  7. <img src="images/temp.jpg" alt="" data-src="images/img-5.jpg" />
  8. <img src="images/temp.jpg" alt="" data-src="images/img-6.jpg" />
  9. <img src="images/temp.jpg" alt="" data-src="images/img-7.jpg" />
  10. <img src="images/temp.jpg" alt="" data-src="images/img-8.jpg" />
  11. <img src="images/temp.jpg" alt="" data-src="images/img-9.jpg" />
  12. <img src="images/temp.jpg" alt="" data-src="images/img-10.jpg" />
  13. <img src="images/temp.jpg" alt="" data-src="images/img-11.jpg" />
  14. <img src="images/temp.jpg" alt="" data-src="images/img-12.jpg" />
  15. <img src="images/temp.jpg" alt="" data-src="images/img-13.jpg" />
  16. <img src="images/temp.jpg" alt="" data-src="images/img-14.jpg" />
  17. <img src="images/temp.jpg" alt="" data-src="images/img-15.jpg" />
  18. <img src="images/temp.jpg" alt="" data-src="images/img-16.jpg" />
  19. <img src="images/temp.jpg" alt="" data-src="images/img-17.jpg" />
  20. </ul>
  21. //js代码
  22. <script>
  23. //获取图片列表
  24. const imgs = document.querySelectorAll(".imgs img");
  25. //获取当前视口高度
  26. const clientHeight = document.documentElement.clientHeight;
  27. window.addEventListener("scroll", layzyload);
  28. window.addEventListener("load", layzyload);
  29. function layzyload() {
  30. //获取滚动高度
  31. let scrollTop = document.documentElement.scrollTop;
  32. //遍历当前图片是否到了可视区 图片到顶部的高度小于视口+滚动高度,即认为图片进入可视区
  33. imgs.forEach((img) => {
  34. if (img.offsetTop < scrollTop + clientHeight) {
  35. setTimeout(() => (img.src = img.dataset.src), 500);
  36. }
  37. });
  38. }
  39. </script>

轮播图

  1. //html代码
  2. <div class="container">
  3. <!-- 1. 图片组 -->
  4. <nav class="imgs">
  5. <a href="#"
  6. ><img src="banner/banner1.jpg" alt="" data-index="1" class="active"
  7. /></a>
  8. <a href="#"><img src="banner/banner2.jpg" alt="" data-index="2" /></a>
  9. <a href="#"><img src="banner/banner3.jpg" alt="" data-index="3" /></a>
  10. <a href="#"><img src="banner/banner4.jpg" alt="" data-index="4" /></a>
  11. </nav>
  12. <!-- 2. 与图片组对应的按钮组(一个个独立的,数量与图片数量是相同的) -->
  13. <nav class="btns">
  14. <!-- 这些小按钮应该是js根据图片数量动态来创建 -->
  15. </nav>
  16. <!-- 3. 翻页按钮(只有二个,分别在左右) -->
  17. <nav class="skip">
  18. <!-- &lt;: 实体符号 -->
  19. <a href="#" class="prev">&lt;</a>
  20. <a href="#" class="next">&gt;</a>
  21. </nav>
  22. </div>
  23. //JS代码
  24. <script>
  25. // 获取相关的元素对象
  26. // 图片组
  27. const imgs = document.querySelectorAll(".container > .imgs img");
  28. // 按钮组
  29. const btnGroup = document.querySelector(" .container > .btns");
  30. // 翻页按钮
  31. const skip = document.querySelector(" .container > .skip");
  32. // 自动生成按钮组,数量与图片数量一致
  33. function autoCreateBtns(ele, imgLength) {
  34. // 使用文档片断
  35. const frag = document.createDocumentFragment();
  36. for (let i = 0; i < imgLength; i++) {
  37. const a = document.createElement("a");
  38. // #: 防止默认行为,更加规范用 ev.preventDefault();
  39. a.href = "#";
  40. // 自定义数据属性
  41. a.dataset.index = i + 1;
  42. // 为第一个按钮添加高亮,这是默认的
  43. if (i === 0) a.classList.add("active");
  44. frag.appendChild(a);
  45. }
  46. ele.appendChild(frag);
  47. }
  48. // 调用该函数自动生成与图片一一对应的小按钮
  49. autoCreateBtns(btnGroup, imgs.length);
  50. // 获取到刚生成的按钮组中所有按钮
  51. const btns = document.querySelectorAll(" .container > .btns > *");
  52. // 下面声明2个公共函数
  53. // 1. 获取激活的元素
  54. function getActiveEle(eles) {
  55. let activities = Array.from(eles).filter(img =>
  56. img.classList.contains("active")
  57. );
  58. return activities.shift();
  59. }
  60. // 2. 设置激活的元素
  61. function setActiveEle(btnIndex) {
  62. // 同时遍历所有图片与按钮
  63. [imgs, btns].forEach(arr => {
  64. // 取消当前激活元素的状态
  65. getActiveEle(arr).classList.remove("active");
  66. // 根据当前用户点击的按钮索引,重置应该激活的元素
  67. arr.forEach(item => {
  68. if (item.dataset.index === btnIndex) {
  69. item.classList.add("active");
  70. }
  71. });
  72. });
  73. }
  74. // 为每一个独立的小按钮添加事件,不要使用事件代理
  75. btns.forEach(btn =>
  76. btn.addEventListener(
  77. "click",
  78. ev => setActiveEle(ev.target.dataset.index),
  79. false
  80. )
  81. );
  82. // 作业1: 为每个翻页按钮添加事件完成图片翻页(兄弟节点的处理)
  83. skip.addEventListener("click", skipImg, false);
  84. // 单独写一个事件监听器,为后面的事件自动派发做准备
  85. skip.children[0].addEventListener("click", skipImg, false);
  86. // 将前后翻页,使用一个回调统一处理
  87. function skipImg(ev) {
  88. // 当前激活的图片,实际上这里用不到它,而应该用它的父级<a>来判断是否存在兄弟节点
  89. let currentImg = getActiveEle(imgs);
  90. // 当前图片组父元素,注意<img>父级是<a>,<a>的父级才是需要的父节点
  91. let parentEle = currentImg.parentElement.parentElement;
  92. // 当前元素的前一个兄弟节点:previousElementSibling;
  93. let prevEle = currentImg.parentElement.previousElementSibling;
  94. // 当前元素的下一个兄弟节点:nextElementSibling;
  95. let nextEle = currentImg.parentElement.nextElementSibling;
  96. // 第一张图片, firstElementChild第一个子元素
  97. let firstImg = parentEle.firstElementChild.firstElementChild;
  98. // 最后一张图片, firstElementChild, 最后一个子元素
  99. let lastImg = parentEle.lastElementChild.firstElementChild;
  100. let activeImg = currentImg;
  101. // 向前翻页
  102. if (ev.target.classList.contains("prev")) {
  103. // 如果存在前一张图片,就使用它,否则就使用最后一张图片来更新它,形成循环显示的效果
  104. let activeImg =
  105. prevEle !== null ? prevEle.firstElementChild : lastImg;
  106. // 使用激活元素来同步更新图片与按钮
  107. setActiveEle(activeImg.dataset.index);
  108. }
  109. // 向后翻页
  110. if (ev.target.classList.contains("next")) {
  111. // 如果不存在下一张图片,就用第一张图片更新它
  112. let activeImg =
  113. nextEle !== null ? nextEle.firstElementChild : firstImg;
  114. setActiveEle(activeImg.dataset.index);
  115. }
  116. }
  117. // 作业2: 图片每隔2秒自动播放(定时器,事件自动派发)
  118. let timer = null;
  119. const slider = document.querySelector(".container");
  120. slider.addEventListener("mouseout", startTimer, false);
  121. slider.addEventListener("mouseover", clearTimer, false);
  122. // 启动定时器
  123. function startTimer() {
  124. // 创建自定义事件对象
  125. const clickEvent = new Event("click");
  126. timer = setInterval(
  127. () => skip.children[0].dispatchEvent(clickEvent),
  128. 2000
  129. );
  130. }
  131. // 清除定时器
  132. function clearTimer() {
  133. clearInterval(timer);
  134. }
  135. </script>
Correcting teacher:天蓬老师天蓬老师

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