【零基础JavaScript入门 | Day7】三大交互案例深度解析|从DOM操作到组件化开发

【零基础JavaScript入门 | Day7】三大交互案例深度解析|从DOM操作到组件化开发

🌟今日知识图谱:

✅ 事件驱动编程 → 按钮交互与定时器控制

✅ 组件化思维 → 可复用UI模块开发

✅ 用户体验优化 → 动画与状态反馈设计

✅ 工程化实践 → 代码组织与维护技巧


案例一:课堂点名小助手

html 复制代码
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    * {
      margin: 0;
      padding: 0;
    }

    h2 {
      text-align: center;
    }

    .box {
      width: 600px;
      margin: 50px auto;
      display: flex;

    }

    .qs {
      width: 450px;
      height: 40px;
      color: red;
    }

    .btns {
      text-align: center;
    }

    .btns button {
      width: 100px;
      height: 35px;
      margin: 0 40px;
    }
  </style>
</head>

<body>
  <h2>随机点名</h2>
  <div class="box">
    <span>名字是:</span>
    <div class="qs">这里显示姓名</div>
  </div>
  <div class="btns">
    <button class="start">开始</button>
    <button class="end">结束</button>
  </div>
  <script>
    const arr = ['张三', '李四', '王五', '赵六', '田七', '王八', '陈九', '韩十']
    // 获取对象
    const qs = document.querySelector('.qs')
    const start = document.querySelector('.start')
    // 定时器的全局变量
    let n = null
    // 声明全局变量
    let random = null
    //添加点击事件
    start.addEventListener('click', function () {
      n = setInterval(function () {
        const random = Math.floor(Math.random() * arr.length)
        qs.innerHTML = arr[random]
      }, 100)

      // 如果数组里面只剩一个,不需要抽取
      if (arr.length === 1) {
        start.disabled = true
        end.disabled = true
      }
    })
    // 关闭点击模块
    const end = document.querySelector('.end')
    end.addEventListener('click', function () {
      clearInterval(n)
      arr.splice(random, 1)
      console.log(arr)
    })



  </script>
</body>

</html>

🔍 功能升级建议

  1. 音效增强 :添加点击音效(audio.play())
  2. 动画效果:名字滚动时添加CSS旋转动画
  3. 数据持久化localStorage保存剩余名单

案例二:智能搜索提示框

html 复制代码
<!DOCTYPE html>
<html lang="zh-CN">

<head>
  <meta charset="UTF-8">
  <title>小米搜索框练习模板</title>
  <style>
    /* 容器样式 */
    .search-box {
      margin: 100px auto;
      width: 500px;
      text-align: center;
    }

    /* 搜索容器(包含输入框和图标的父元素) */
    .search-container {
      position: relative;
      display: inline-block;
    }

    /* 默认输入框样式 */
    .search-input {
      width: 100px;
      /* 默认宽度 */
      height: 35px;
      padding: 0 30px;
      border: 1px solid #e0e0e0;
      border-radius: 17px;
      outline: none;
      transition: all 0.3s;
      /* 添加过渡动画 */
    }

    /* 搜索图标样式 */
    .search-icon {
      position: absolute;
      left: 10px;
      top: 50%;
      transform: translateY(-50%);
      width: 18px;
      height: 18px;
      background: url('data:image/svg+xml;utf8,<svg fill="#999999" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg"><path d="M945.066667 898.133333l-147.2-147.2c44.8-32 83.2-72.533333 108.8-121.6 34.133333-57.6 51.2-121.6 51.2-185.6 0-164.266667-134.4-300.8-300.8-300.8-166.4 0-300.8 134.4-300.8 300.8s134.4 300.8 300.8 300.8c61.866667 0 123.733333-19.2 174.933333-53.333333 44.8-32 83.2-72.533333 108.8-121.6l147.2 147.2c6.4 6.4 14.933333 8.533333 23.466667 8.533333s17.066667-2.133333 23.466666-8.533333c10.666667-12.8 10.666667-34.133333-2.133333-46.933334zM460.8 742.4c-151.466667 0-275.2-123.733333-275.2-275.2s123.733333-275.2 275.2-275.2 275.2 123.733333 275.2 275.2-123.733333 275.2-275.2 275.2z"/></svg>');
      pointer-events: none;
    }

    .result-list {
      display: none;
      list-style: none;
      padding: 0;
      margin: 0;
      position: absolute;
      top: 100%;
      left: 0;
      width: 100%;
      background-color: #fff;
      border: 1px solid #ccc;
      border-radius: 4px;
      box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);

    }

    .result-list a {
      text-decoration: none;
      color: #333;
      display: block;
      padding: 5px;
      border-bottom: 1px solid #ccc;
      cursor: pointer;
    }

    .result-list a:hover {
      background-color: #f0f0f0;
    }
  </style>
</head>

<body>
  <!-- 搜索框结构 -->
  <div class="search-box">
    <div class="search-container">
      <!-- 输入框 -->
      <input type="text" class="search-input" placeholder="搜索内容">
      <ul class="result-list">
        <li><a href="#">全部商品</a></li>
        <li><a href="#">小米15</a></li>
        <li><a href="#">小米14</a></li>
        <li><a href="#">红米k60</a></li>
        <li><a href="#">小米笔记本</a></li>
        <li><a href="#">小米15ultra</a></li>
        <li><a href="#">小米14pro</a></li>
      </ul>

    </div>
  </div>

  <script>
    // 获取元素
    const input = document.querySelector('.search-input');
    const ul = document.querySelector('.result-list');
    const searchContainer = document.querySelector('.search-container');
    // 监听事件,获得焦点
    input.addEventListener('focus', function () {
      ul.style.display = 'block';
    })
    // 监听事件,失去焦点
    input.addEventListener('blur', function () {
      ul.style.display = 'none';
    })
  </script>
</body>

</html>

✨ 新增功能模块

  1. 热门搜索标签:展示本周Top5搜索词
  2. 历史记录:自动保存最近10条搜索记录
  3. 键盘导航:方向键选择建议项

案例三:交互式轮播组件

html 复制代码
<!DOCTYPE html>
<html lang="en">

<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>
  <style>
    * {
      box-sizing: border-box;
    }

    .slider {
      width: 240px;
      height: 450px;
      overflow: hidden;
    }

    .slider-poster {
      width: 100%;
      height: 320px;
    }

    .slider-poster img {
      width: 100%;
      height: 100%;
      display: block;
    }

    .slider-footer {
      height: 80px;
      background-color: rgb(100, 67, 68);
      padding: 12px 12px 0 12px;
      position: relative;
    }

    .slider-footer .toggle {
      position: absolute;
      right: 0;
      top: 12px;
      display: flex;
    }

    .slider-footer .toggle button {
      margin-right: 12px;
      width: 28px;
      height: 28px;
      appearance: none;
      border: none;
      background: rgba(255, 255, 255, 0.1);
      color: #fff;
      border-radius: 4px;
      cursor: pointer;
    }

    .slider-footer .toggle button:hover {
      background: rgba(255, 255, 255, 0.2);
    }

    .slider-footer p {
      margin: 0;
      color: #fff;
      font-size: 18px;
      margin-bottom: 10px;
    }

    .slider-indicator {
      margin: 0;
      padding: 0;
      list-style: none;
      display: flex;
      align-items: center;
    }

    .slider-indicator li {
      width: 8px;
      height: 8px;
      margin: 4px;
      border-radius: 50%;
      background: #fff;
      opacity: 0.4;
      cursor: pointer;
    }

    .slider-indicator li.active {
      width: 12px;
      height: 12px;
      opacity: 1;
    }
  </style>
</head>

<body>
  <div class="slider">
    <div class="slider-poster">
      <img src="./images/p1.jpg" alt="" />
    </div>
    <div class="slider-footer">
      <p>魔法石</p>
      <ul class="slider-indicator">
        <li class="active"></li>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
      </ul>
      <div class="toggle">
        <button class="prev">&lt;</button>
        <button class="next">&gt;</button>
      </div>
    </div>
  </div>
  <script>
    // 1. 初始数据
    const pData = [
      { url: './images/p1.jpg', title: '魔法石', color: 'rgb(36, 156, 200)' },
      { url: './images/p2.jpg', title: '密室', color: 'rgb(43, 35, 26)' },
      { url: './images/p3.jpg', title: '阿兹卡班的囚徒', color: 'rgb(36, 31, 33)' },
      { url: './images/p4.jpg', title: '火焰杯', color: 'rgb(45, 110, 113)' },
      { url: './images/p5.jpg', title: '凤凰社', color: 'rgb(67, 90, 92)' },
      { url: './images/p6.jpg', title: '死亡圣器(上)', color: 'rgb(7, 66, 73)' },
      { url: './images/p7.jpg', title: '死亡圣器(下)', color: 'rgb(53, 29, 25)' },
    ]
    // 获取对象
    const img = document.querySelector('.slider-poster img')
    const footer = document.querySelector('.slider-footer')
    const p = document.querySelector('.slider-footer p')
    const next = document.querySelector('.next')
    let i = 0
    next.addEventListener('click', function () {
      i++
      if (i === pData.length) {
        i = 0
      }
      img.src = pData[i].url
      footer.style.backgroundColor = pData[i].color
      p.innerHTML = pData[i].title
      document.querySelector('.slider-indicator .active').classList.remove('active')
      document.querySelector(`.slider-indicator li:nth-child(${i + 1})`).classList.add('active')
    })

    const prev = document.querySelector('.prev')
    prev.addEventListener('click', function () {
      i--
      if (i <= -1) {
        i = 6
      }
      common()
    })
    function common() {
      img.src = pData[i].url
      footer.style.backgroundColor = pData[i].color
      p.innerHTML = pData[i].title
      document.querySelector('.slider-indicator .active').classList.remove('active')
      document.querySelector(`.slider-indicator li:nth-child(${i + 1})`).classList.add('active')
    }

    // 自动播放
    let n = setInterval(function () {
      next.click()
    }, 1000)

    // 鼠标经过盒子时,停止播放
    const slider = document.querySelector('.slider')
    slider.addEventListener('mouseenter', function () {
      clearInterval(n)
    })

    // 鼠标离开盒子时,继续播放
    slider.addEventListener('mouseleave', function () {
      n = setInterval(function () {
        next.click()
      }, 1000)
    })

  </script>


</body>

</html>

🚀 企业级优化

  1. 无限循环模式:克隆首尾元素实现无缝滚动

🎯 共性优化策略

优化方向 案例一 案例二 案例三
代码结构 减少全局变量 模块化封装 类组件化
用户体验 添加加载动画 输入防抖 滑动过渡
功能扩展 名单导入导出 搜索联想 缩略图导航

📌 注意事项

  1. 所有修改需保持原始HTML结构
  2. 优先使用textContent替代innerHTML防XSS攻击
  3. 定时器务必及时清理(clearInterval
相关推荐
Elec_z30 分钟前
网络深处的守门人
开发语言·网络
闪电麦坤952 小时前
C#:Time.deltaTime
开发语言·c#
Alfadi联盟 萧瑶3 小时前
Python-Django入手
开发语言·python·django
-代号95275 小时前
【JavaScript】十二、定时器
开发语言·javascript·ecmascript
勘察加熊人5 小时前
c++实现录音系统
开发语言·c++
self-discipline6345 小时前
【Java】Java核心知识点与相应面试技巧(七)——类与对象(二)
java·开发语言·面试
wei3872452325 小时前
java笔记02
java·开发语言·笔记
CANI_PLUS6 小时前
python 列表-元组-集合-字典
开发语言·python
灵感__idea6 小时前
JavaScript高级程序设计(第5版):扎实的基本功是唯一捷径
前端·javascript·程序员
老秦包你会6 小时前
QT第六课------QT界面优化------QSS
开发语言·qt