js 急速入门之六(classList,dataset对象,选项卡,一键换肤,图片懒加载,简易轮播图)

classList:设置元素的类样式

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <title>classList</title>
  7. <style>
  8. .red {
  9. color:red;
  10. }
  11. .bg {
  12. background-color: yellow;
  13. }
  14. .green{
  15. color:green;
  16. }
  17. </style>
  18. </head>
  19. <body>
  20. <!-- <p class="red bg">欢迎</p> -->
  21. <p>欢迎</p>
  22. <script>
  23. const p =document.querySelector("p");
  24. // p.className='red';
  25. // p.className='red bg';
  26. // classList:用来动态的设置元素的类样式
  27. //对象有属性和方法
  28. // p.classList.add("red");
  29. // p.classList.add("bg")
  30. // p.classList.remove("bg");
  31. // p.classList.add("green","bg");
  32. // p.classList.replace("green","red");
  33. //toggle()动态切换:如果样式表有red 就移除,没有就添加
  34. p.classList.toggle("red");
  35. </script>
  36. </body>
  37. </html>

dataset对象:自定义属性

  1. <!-- id:预定义属性 -->
  2. <!-- email:自定义属性 -->
  3. <p id='aaa' data-email='a@php.cn' data-my-age='40' data-index="1">我的资料</p>
  4. <script>
  5. const p = document.querySelector("p");
  6. //使用getAttribute()方法获取自定义属性
  7. // const email = p.getAttribute("email");
  8. // console.log(email);
  9. // dataset:读写自定义属性,但是这个属性在HTML中必须使用 'data-' 为前缀
  10. // js代码中data- 前缀必须省;之后还有连接线时,连接线必须省去,原连接线后的首字母必须大写
  11. console.log(p.dataset.email);
  12. console.log(p.dataset.myAge);
  13. console.log(p.dataset.index);
  14. </script>

案例

选项卡

知识点:
数组的遍历: forEach()
数组的筛选: filter()
classList属性:classList.remove(),classList.add()

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8" />
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  6. <title>选项卡</title>
  7. <style>
  8. * {
  9. margin: 0;
  10. padding: 0;
  11. box-sizing: border-box;
  12. }
  13. a {
  14. text-decoration: none;
  15. color: #555;
  16. }
  17. a:hover {
  18. text-decoration: underline;
  19. color: red;
  20. }
  21. li {
  22. list-style: none;
  23. line-height: 1.6em;
  24. }
  25. li:hover{
  26. cursor:default;
  27. }
  28. .tabs {
  29. width: 300px;
  30. height: 300px;
  31. margin: 30px;
  32. background-color: #e6e6e6;
  33. display: flex;
  34. flex-direction: column;
  35. }
  36. .tab {
  37. height: 36px;
  38. display: flex;
  39. }
  40. .tab li {
  41. flex: auto;
  42. text-align: center;
  43. line-height: 36px;
  44. background-color: #fff;
  45. }
  46. .tab li.active {
  47. background-color: #e6e6e6;
  48. }
  49. .tab li:hover {
  50. cursor: pointer;
  51. }
  52. .item{
  53. padding: 20px;
  54. display: none;
  55. }
  56. .item.active {
  57. display: block;
  58. }
  59. </style>
  60. </head>
  61. <body>
  62. <div class="tabs">
  63. <!-- 导航 -->
  64. <ul class="tab">
  65. <li class="active" data-index="1">省内</li>
  66. <li data-index="2">国内</li>
  67. <li data-index="3">国际</li>
  68. </ul>
  69. <!-- details -->
  70. <ul data-index="1" class="item active" >
  71. <li><a href="">省内新闻</a></li>
  72. <li><a href="">省内新闻省内新闻</a></li>
  73. <li><a href="">省内新闻省内新闻省内新闻</a></li>
  74. </ul>
  75. <ul data-index="2" class="item">
  76. <li><a href="">国内国内国内国内</a></li>
  77. <li><a href="">国内国内国内国内国内</a></li>
  78. <li><a href="">国内国内国内国内</a></li>
  79. </ul>
  80. <ul data-index="3" class="item">
  81. <li><a href="">国际国际国际国际国际国际</a></li>
  82. <li><a href="">国际国际国际国际国际</a></li>
  83. <li><a href="">国际国际国际国际</a></li>
  84. </ul>
  85. </div>
  86. <script>
  87. const tab = document.querySelector(".tab");
  88. const items = document.querySelectorAll(".item");
  89. //1. 清空之前所有出于激活状态的选项卡,并将当前点击对象激活
  90. tab.onclick = (ev) => {
  91. // 事件绑定对象
  92. // console.log(ev.currentTarget);
  93. //事件触发对象
  94. // console.log(ev.target);
  95. [...tab.children].forEach((item) => item.classList.remove("active"));
  96. ev.target.classList.add("active");
  97. //2. 根据自定义属性data-index找到对应的列表并显示
  98. //NodeList对象内置了forEach接口
  99. items.forEach(item => item.classList.remove("active"));
  100. console.log(ev.target);
  101. [...items].filter(item => item.dataset.index === ev.target.dataset.index)[0].classList.add("active");
  102. };
  103. </script>
  104. </body>
  105. </html>

一键换肤

知识点:
动态修改 body.style.backgroundImage

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8" />
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  6. <title>一键换肤</title>
  7. <style>
  8. .container {
  9. width: 300px;
  10. display: grid;
  11. grid-template-columns: repeat(3,1fr);
  12. column-gap:10px;
  13. }
  14. .container>img{
  15. width: 100%;
  16. border:3px solid #fff;
  17. opacity: 0.6;
  18. }
  19. .container > img:active {
  20. opacity: 1;
  21. }
  22. .container > img:hover {
  23. opacity: 1;
  24. cursor:pointer;
  25. width: 105%;
  26. }
  27. body {
  28. background-image: url("static/images/1.jpg");
  29. background-repeat: no-repeat;
  30. background-size: cover;
  31. }
  32. </style>
  33. </head>
  34. <body>
  35. <div class="container">
  36. <img src="static/images/1.jpg" alt="" />
  37. <img src="static/images/2.jpg" alt="" />
  38. <img src="static/images/3.jpg" alt="" />
  39. </div>
  40. <script>
  41. //事件代理,不需要给每个图片的缩略图添加点击事件,只需要给父元素添加就可以了
  42. // document.querySelector(".container").onclick = ev=>document.body.backgroundImage = "url("+ev.target.src+")";
  43. const box = document.querySelector(".container");
  44. box.onclick = function (ev) {
  45. const body = document.body;
  46. let imgUrl = "url("+ev.target.src+")";
  47. body.style.backgroundImage = imgUrl;
  48. }
  49. </script>
  50. </body>
  51. </html>

图片懒加载

懒加载原理
先将图片的url地址存到自定义属性 data-src 中,当图片top值<视口+滚动高度时 用 data-src 替换 src
img.offsetTop < clientHeight + document.documentElement.scrollTop

知识点:setTimeout(),两个事件 scroll,load

  1. //视口高度
  2. let viewHeight = document.documentElement.clientHeight;
  3. //滚动高度
  4. document.onscroll = ev=>{
  5. console.log(document.documentElement.scrollTop);
  6. }
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8" />
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  6. <title>图片懒加载</title>
  7. <style>
  8. .container {
  9. width: 500px;
  10. display: grid;
  11. gap: 10px;
  12. grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  13. }
  14. .container img {
  15. width: 100%;
  16. }
  17. </style>
  18. </head>
  19. <body>
  20. <div class="container">
  21. <img src="images/temp.jpg" alt="" data-src="images/img-1.jpg" />
  22. <img src="images/temp.jpg" alt="" data-src="images/img-2.jpg" />
  23. <img src="images/temp.jpg" alt="" data-src="images/img-3.jpg" />
  24. <img src="images/temp.jpg" alt="" data-src="images/img-4.jpg" />
  25. <img src="images/temp.jpg" alt="" data-src="images/img-5.jpg" />
  26. <img src="images/temp.jpg" alt="" data-src="images/img-6.jpg" />
  27. <img src="images/temp.jpg" alt="" data-src="images/img-7.jpg" />
  28. <img src="images/temp.jpg" alt="" data-src="images/img-8.jpg" />
  29. <img src="images/temp.jpg" alt="" data-src="images/img-9.jpg" />
  30. <img src="images/temp.jpg" alt="" data-src="images/img-10.jpg" />
  31. </div>
  32. <script>
  33. // const imgs =document.images;
  34. const images = document.querySelectorAll(".container img");
  35. const clientHeight = document.documentElement.clientHeight;
  36. window.addEventListener("scroll", layzyload);
  37. window.addEventListener("load", layzyload);
  38. function layzyload() {
  39. images.forEach((img) => {
  40. if (img.offsetTop < clientHeight + document.documentElement.scrollTop)
  41. setTimeout(() => (img.src = img.dataset.src), 500);
  42. });
  43. }
  44. // images
  45. </script>
  46. </body>
  47. </html>

轮播图

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8" />
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  6. <title>轮播图</title>
  7. <link rel="stylesheet" href="banner/style.css" />
  8. </head>
  9. <body>
  10. <div class="container">
  11. <!-- 1. 图片组 -->
  12. <nav class="imgs">
  13. <a href="#"
  14. ><img src="banner/banner1.jpg" alt="" data-index="1" class="active"
  15. /></a>
  16. <a href="#"><img src="banner/banner2.jpg" alt="" data-index="2" /></a>
  17. <a href="#"><img src="banner/banner3.jpg" alt="" data-index="3" /></a>
  18. <a href="#"><img src="banner/banner4.jpg" alt="" data-index="4" /></a>
  19. </nav>
  20. <!-- 2. 图片小按钮 -->
  21. <nav class="btns">
  22. <!-- 应该根据图片的数量自动生成 -->
  23. <!-- <a href="" data-index="1" class="active"></a>
  24. <a href="" data-index="2"></a>
  25. <a href="" data-index="3"></a>
  26. <a href="" data-index="4"></a> -->
  27. </nav>
  28. <!-- 3. 翻页按钮 -->
  29. <nav class="skip">
  30. <a href="#" class="prev">&lt;</a>
  31. <a href="#" class="next">&gt;</a>
  32. </nav>
  33. </div>
  34. <script>
  35. // 所有图片
  36. const imgs = document.querySelectorAll(".container > .imgs img");
  37. //按钮组
  38. const btnGroup = document.querySelector(".container > .btns");
  39. // 翻页按钮
  40. const skip = document.querySelectorAll(".container > .skip > a");
  41. // 创建出一组与图片数量一致的小按钮
  42. function autoCreateBtns(ele, imgCount) {
  43. const frag = document.createDocumentFragment();
  44. for (let i = 0; i < imgCount; i++) {
  45. const a = document.createElement("a");
  46. a.href = "#";
  47. a.dataset.index = i + 1;
  48. if (i === 0) a.classList.add("active");
  49. frag.appendChild(a);
  50. }
  51. ele.appendChild(frag);
  52. }
  53. // 调用创建小按钮的函数
  54. autoCreateBtns(btnGroup, imgs.length);
  55. // 为刚刚生成的小按钮添加点击事件
  56. const btns = document.querySelectorAll(".container > .btns > *");
  57. // 写两个公共函数
  58. // 1. 获取激活的元素
  59. function getActiveEle(eles) {
  60. let activities = [...eles].filter((img) =>
  61. img.classList.contains("active")
  62. );
  63. return activities.shift();
  64. }
  65. // 2. 设置激活元素,根据按钮索引更新正在显示的图片
  66. function setActiveEle(btnIndex) {
  67. [imgs, btns].forEach((arr) => {
  68. // 将之前的状态重置到初始化
  69. getActiveEle(arr).classList.remove("active");
  70. arr.forEach((item) => {
  71. if (item.dataset.index === btnIndex) {
  72. item.classList.add("active");
  73. }
  74. });
  75. });
  76. }
  77. btns.forEach((btn) =>
  78. btn.addEventListener("click", (ev) =>
  79. setActiveEle(ev.target.dataset.index)
  80. )
  81. );
  82. let iMax = imgs.length;
  83. //上一张
  84. let prevSkip = document.querySelector(".prev");
  85. prevSkip.addEventListener("click", () => {
  86. let iIndex = getActiveEle(imgs).dataset.index;
  87. let iPrev = parseInt(iIndex) - 1;
  88. iPrev < 1
  89. ? setActiveEle(iMax.toString())
  90. : setActiveEle(iPrev.toString());
  91. });
  92. //下一张
  93. let nextSkip = document.querySelector(".next");
  94. nextSkip.addEventListener("click", () => {
  95. let iIndex = getActiveEle(imgs).dataset.index;
  96. let iNext = parseInt(iIndex) + 1;
  97. iNext > iMax
  98. ? setActiveEle("1")
  99. : setActiveEle(iNext.toString());
  100. });
  101. //事件派发
  102. startInterval = function () {
  103. const ev = new Event("click");
  104. nextSkip.dispatchEvent(ev);
  105. };
  106. //使用间歇式定时器
  107. let intervalID = setInterval(startInterval, 2000);
  108. let container = document.querySelector(".container");
  109. container.addEventListener("mouseover", () => clearInterval(intervalID));
  110. container.addEventListener(
  111. "mouseleave",
  112. () => (intervalID = setInterval(startInterval, 2000))
  113. );
  114. </script>
  115. </body>
  116. </html>

小结:调试过程中因为没有将事件派发封装,直接使用 setInterval() 设置派发造成一直无法达到效果。
由于没有了解setInterval用法造成时间的浪费,吃一堑长一智吧。

更多相关文章

  1. 一文教你实现 SpringBoot 中的自定义 Validator 和错误信息国际
  2. ANDROID SDK配置步骤
  3. Android(安卓)SDK代理服务器解决国内不能更新下载问题
  4. Android(安卓)国际化 语言相关 和 打包 多渠道配置
  5. 国内优秀Android学习资源汇总全集
  6. Android中App内部切换语言包
  7. Android进阶之如何实现国际化和各国Values文件夹命名
  8. Android(安卓)SDK Manager 安装和使用国内镜像更新下载方法
  9. 别再抱怨了,国内这么多优秀的Android资源你都知道吗?

随机推荐

  1. 在服务器上使用 gradle 打包 android 源
  2. android与js交互-jsbridge
  3. Android中自定义Dialog样式
  4. android Home键的截获
  5. Android官方入门文档[6]添加Action按钮
  6. Android 编写使用root权限的android应用
  7. android 随手记 遍历文件夹下的文件有多
  8. 开发板部分总结
  9. android SQLite 事物处理
  10. 57.EasyRecyclerViewSidebar