JavaScript编程基础(七)经典实战之轮播图构造与功能模块的编写

原创 阁主  2026-03-28 09:18:03  阅读 5926 次 评论 0 条
摘要:

继续上次的JavaScript编程基础(六)继续学习,简单记录学习PHP中文网23期JavaScript基础知识,内容包括:经典实战之自动翻页轮播图

介绍

轮播图的话,当下比较流行的方式就包含了图片组和按钮组,从功能上看可以得出按钮数量===图片数量,点击按钮可以切换对应的图片,用户如果没有任何操作时会自动完成轮播效果。本文记录此效果全部使用“模块”完成。
轮播图效果

代码

index.html:

<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>轮播图实战</title>
    <link rel="stylesheet" href="css/style.css" />
  </head>
  <body>
    <div class="slideshow">
      <!-- 图片组和按钮组全部由模块动态创建 -->

      <!-- 1. 图片组 -->
      <div class="imgs"></div>

      <!-- 2. 按钮组 -->
      <!-- 按钮组中的按钮数量,必须和图片的数量完全相同 -->
      <div class="btns"></div>
    </div>

    <script type="module">
      // 获取图片组的入口
      const imgs = document.querySelector(".imgs");

      // 获取按钮组的入口
      const btns = document.querySelector(".btns");

      /**
       * 当前轮播图至少需要4个函数
       * 1. 创建图片组
       * 2. 创建按钮组
       * 3. 创建按钮事件: 实现图片的切换
       * 4. 定时轮播器: 间歇式的定时器
       */

      // 导入轮播图模块: slideshow.js

      import slide from "./js/slideshow.js";
      console.log(slide);

      window.onload = function () {
        // 1. 创建图片组
        slide.createImgs(imgs);

        // 2. 创建按钮组
        slide.createBtns(imgs, btns);

        // 3. 创建按钮事件: 实现图片的切换
        // 注: 这里不能用事件代理/委托
        // btns.onclick = function(){}
        [...btns.children].forEach(function (btn) {
          btn.onclick = function () {
            slide.switchImg(this, imgs);
          };
        });

        // 4. 定时轮播器: 间歇式的定时器

        /**
         * 首尾相连的数组(队列)
         * 0,1,2
         * 1,2,0
         * 2,0,1
         * 0,1,2
         */

        //取按钮的对象转为数组
        // const btnsArr = [...btns.children]
        // console.log(btnsArr)

        // Object.keys(): 返回对象索引组成的数组
        // console.log(Object.keys({ a: 1, b: 2, c: 3 }));
        // console.log(Object.keys([1, 5, 30, 222]));

        // console.log(Object.keys(btnsArr))

        // 间歇式定时器,第2秒换一张图片
        setInterval(
          function (btnsArr, btnKeys) {
            console.log(btnsArr);
            console.log(btnKeys);
            slide.timePlay(btnsArr, btnKeys);
          },
          2000,
          // 后面两个参数是传递给回调函数的参数,这边是按钮组对象和按钮组索引组成的数组
          [...btns.children],
          Object.keys([...btns.children])
        );
      };
    </script>
  </body>
</html>

style.css:

body {
  background-color: #eee;
}

/* 轮播图容器 */
.slideshow {
  width: 240px;
  height: 360px;
  /* em / rem  */
}

/* 图片容器 */
.slideshow .imgs {
  /* inherit从父元素获取值 */
  width: inherit;
  height: inherit;
  /* width: 100%;
  height: 100%; */
}

/* 图片适应 */
.slideshow img {
  width: 100%;
  height: 100%;
  border-radius: 10px;

  /* ? 默认全隐藏 */
  display: none;
}

/* 设置图片的激活状态 */
.slideshow img.active {
  display: block;
}

.slideshow img:hover {
  cursor: pointer;
}

/* ------ 按钮容器 ------- */

/* 按钮容器 */
.slideshow .btns {
  display: flex;
  place-content: center;

  position: relative;
  top: -40px;

  /* transform: translateY(-40px); */
}

.slideshow .btns > span {
  background-color: rgba(233, 233, 233, 0.8);
  height: 16px;
  width: 16px;
  border-radius: 50%;
  margin: 5px;
}

.slideshow .btns > span.active {
  background-color: orangered;
}

.slideshow .btns > span:hover {
  cursor: pointer;
}

slideshow.js:

// 轮播图的功能模块

// 导入图片组的数据(图片信息)
import imgArr from "./data.js";

/**
 * 当前轮播图至少需要4个函数
 * 1. 创建图片组
 * 2. 创建按钮组
 * 3. 创建按钮事件: 实现图片的切换
 * 4. 定时轮播器: 间歇式的定时器
 */

/**
 * @desc 创建图片组
 * @param {DOMElement} imgs - 图片容器
 */

function createImgs(imgs) {
  // 使用文档片断来优化,将图片的生成与挂载放在内存中完成,以减少页面渲染和抖动

  // 创建文档片断对象
  const frag = new DocumentFragment();

  for (let i = 0; i < imgArr.length; i++) {
    // 1. 创建图片元素<img>
    const img = document.createElement("img");
    console.log(i, img);

    // 2. 为图片添加 src, data-key自定义属性
    img.src = imgArr[i].src;
    img.dataset.key = imgArr[i].key;

    // 3. 默认显示第一张: class='active'
    if (i === 0) img.classList.add("active");

    // 4. 为<img>添加click事件,跳转地址,属性是href
    img.onclick = () => (location.href = imgArr[i].url);

    // 5. 将<img>添加文档片断中
    frag.append(img);
  }
  //   将<img>添加到:图片容器中
  imgs.append(frag);
}

// ======================================

/**
 * @desc 创建按钮组
 * @param {DOMElement} imgs - 图片容器
 * @param {DOMElement} btns - 按钮容器
 */
function createBtns(imgs, btns) {
  // 1.  获取到图片的数量
  let length = imgs.childElementCount;

  // 2. 根据图片的数量生成对应的按钮
  // 创建文档片断对象
  const frag = new DocumentFragment();

  for (let i = 0; i < length; i++) {
    const span = document.createElement("span");
    // 添加data-key 实现与图片的data-key的联动(绑定)
    span.dataset.key = imgs.children[i].dataset.key;
    if (i === 0) span.classList.add("active");
    frag.append(span);
  }
  btns.append(frag);
}

// =======================================

/**
 * @desc 创建按钮事件: 实现图片的切换
 * @param {DOMElement} btn - 当前按钮
 * @param {DOMElement} imgs - 图片容器
 */
function switchImg(btn, imgs) {
  // 1. 去掉所有按钮和图片的"激活"状态active
  [...btn.parentNode.children].forEach((btn) => btn.classList.remove("active"));
  [...imgs.children].forEach((img) => img.classList.remove("active"));

  // 2. 将当前用户正在点击的按钮设置为激活active
  btn.classList.add("active");

  // 3. 根据当前按钮的key,找到对应的图片
  //   btn.dataset.key ==> img.dataset.key
  // 获取当前应该显示的图片
  const currImg = [...imgs.children].find(
    (img) => img.dataset.key === btn.dataset.key
  );
  // console.log(currImg);

  // 4. 把这个图片设置为激活active(显示出来)
  currImg.classList.add("active");
}

// ========================================

/**
 * @desc 定时轮播器: 间歇式的定时器
 * @param {DOMElement} btnsArr - 按钮数组(用来绑定事件)
 * @param {DOMElement} btnKeys - 按钮的键构成的数组
 */
function timePlay(btnsArr, btnKeys) {
  // 定时器 + 事件派发
  // setInterval + dispatchEvent
  // 1. 从头部取一个
  let key = btnKeys.shift();
  // 2. 根据索引,从按钮组中找到与该索引对应的按钮,给它自动派发一个点击事件
  btnsArr[key].dispatchEvent(new MouseEvent("click"));
  // 3. 将刚才取出的按钮,再次从尾部添加到按钮数组中,实现首尾相边的效果
  btnKeys.push(key);
}

// ========================================

// 默认导出
export default {
  createImgs,
  createBtns,
  switchImg,
  timePlay,
};
本文地址:https://www.mainblog.cn/332.html
版权声明:本文为原创文章,版权归 阁主 所有,欢迎分享本文,转载请保留出处!
免责申明:有些内容源于网络,没能联系到作者。如侵犯到你的权益请告知,我们会尽快删除相关内容。
NEXT:已经是最新一篇了

评论已关闭!