2. DOM 事件基础 - 注册事件、tab 栏切换(1)之事件监听、随机点名案例、事件类型及实例

1. 事件监听

事件 是在编程时系统内发生的 动作 或者发生的 事情 ,例如用户在网页上 点击 了一个注册按钮,这就是一个 点击事件

事件监听 就是让程序检测是否有事件产生,一旦有事件被触发,就立即调用一个函数做出响应,也称为 注册事件 ,语法:

DOM 事件监听三要素:

示例:

HTML 复制代码
  <body>
    <button>点击有惊喜哦~</button>

    <script>
      let btn = document.querySelector('button')

      btn.addEventListener('click', () => {
        alert('月薪过万')
      })
    </script>
  </body>

注意:

  • 事件类型要 加引号
  • 函数是点击之后再去执行的,每次点击都会执行一次

实例1:点击按钮,关闭二维码

分析:

  • 首先 获取 按钮元素和父盒子元素
  • 点击 的是按钮元素,关闭 的是父盒子
  • 利用 元素样式 的显示/隐藏属性来完成,写法多样,以下示例其中一种
HTML 复制代码
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>JS 事件</title>
    <style>
      .code {
        position: relative;
        margin: 50px auto;
        width: 800px;
      }
      img {
        position: absolute;
        width: 430px;
        height: 435px;
        border: 1px solid #000;
        margin-left: 10px;
      }
      .display {
        display: none;
      }
    </style>
  </head>

  <body>
    <div class="code">
      <button>X</button>
      <img src="./code.png" alt="" />
    </div>

    <script>
      let btn = document.querySelector('button')
      let code = document.querySelector('.code')

      btn.addEventListener('click', () => {
        code.className = 'display'
      })
    </script>
  </body>
</html>

实例2:随机点名

分析:

  • 首先 获取 按钮元素,点击的是按钮
  • 随机 抽取一个名字
  • 名字抽取完毕,利用 元素样式 禁用按钮
HTML 复制代码
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>JS 事件</title>
    <style>
      .box {
        position: relative;
        margin: 50px auto;
        width: 500px;
        height: 200px;
        border: 1px solid #000;
      }
      .box-name {
        margin: 30px auto;
        width: 260px;
        height: 66px;
        background-color: lightgreen;
        font-size: 22px;
        color: white;
        line-height: 66px;
        text-align: center;
      }
      button {
        border: 0;
        width: 77px;
        height: 40px;
        font-size: 18px;
        border-radius: 3px;
        font-weight: bold;
      }
      .start {
        position: absolute;
        top: 125px;
        left: 152px;
        color: red;
      }
      .end {
        position: absolute;
        top: 125px;
        left: 278px;
      }
    </style>
  </head>

  <body>
    <div class="box">
      <div class="box-name">请点击"开始按钮"</div>
      <button class="start">开始</button>
      <button class="end" disabled>停止</button>
    </div>
    <script>
      // 获取元素
      let box_name = document.querySelector('.box-name')
      let start = document.querySelector('.start')
      let end = document.querySelector('.end')

      // 生成随机数
      function getRandom(min, max) {
        return Math.floor(Math.random() * (max - min + 1)) + min
      }

      // 初始化数据
      let arr = ['小红', '小明', '灵犀', '李四', '张三']
      let time = 0

      // 开始按钮监听事件
      start.addEventListener('click', () => {
        end.disabled = false
        start.disabled = true
        time = setInterval(() => {
          let num = getRandom(0, arr.length - 1)
          box_name.innerHTML = arr[num]
        }, 100)
      })

      // 停止按钮监听事件
      end.addEventListener('click', () => {
        start.disabled = false
        end.disabled = true
        clearInterval(time)
      })
    </script>
  </body>
</html>

2. 事件类型

(1)焦点事件:表单搜索实例

HTML 复制代码
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>JS 事件</title>
    <style>
      input {
        height: 30px;
        border: 1px solid #ccc;
        padding-left: 10px;
        outline: none;
      }
      ul {
        display: none;
        list-style: none;
        position: absolute;
        top: 17px;
        left: 0px;
        border: 1px solid orange;
        padding-top: 13px;
        width: 168px;
        padding-left: 13px;
      }
      .box {
        position: relative;
      }
      ul li {
        height: 35px;
      }
      .dis {
        border: 1px solid orange;
      }
    </style>
  </head>

  <body>
    <div class="box">
      <input type="text" placeholder="小米手机" />
      <ul>
        <li>全部商品</li>
        <li>小米14</li>
        <li>小米手机</li>
        <li>小米12</li>
        <li>小米笔记本</li>
      </ul>
    </div>

    <script>
      let input = document.querySelector('input')
      let ul = document.querySelector('ul')

      input.addEventListener('focus', () => {
        input.className = 'dis'
        ul.style.display = 'block'
      })

      input.addEventListener('blur', () => {
        input.classList.remove('dis')
        ul.style.display = 'none'
      })
    </script>
  </body>
</html>

(2)鼠标事件:将上例的焦点事件改成鼠标移入、移出事件,效果相同:

(3)文本事件:记录用户输入的字数

HTML 复制代码
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>JS 事件</title>
    <style>
      #txt {
        width: 500px;
        height: 80px;
        border-radius: 10px;
        padding-left: 17px;
        padding-top: 13px;
        font-size: 20px;
      }
      div {
        position: relative;
        width: 500px;
      }
      p {
        position: absolute;
        top: -12px;
        right: 80px;
      }
      span {
        color: red;
      }
      button {
        position: absolute;
        top: 9px;
        right: -5px;
        width: 71px;
        height: 36px;
        background-color: lightblue;
        border: 0;
        color: #fff;
        font-size: 18px;
        border-radius: 4px;
      }
    </style>
  </head>

  <body>
    <textarea id="txt" cols="30" rows="10" maxlength="100" placeholder="输入文字..."></textarea>
    <div>
      <p><span>0</span> /200</p>
      <button>发布</button>
    </div>

    <script>
      let txt = document.querySelector('#txt')
      let span = document.querySelector('span')

      txt.addEventListener('input', () => {
        // console.log(txt.value) // 用户输入的值
        // console.log(txt.value.length) // 用户输入的长度
        span.innerHTML = txt.value.length
      })
    </script>
  </body>
</html>

(4)鼠标点击事件

需求:用户点击全选,则下面的复选框全部选中;取消全选则全部取消,且文字对应变化

HTML 复制代码
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>JS 事件</title>
    <style>
      table,
      tr,
      td,
      th {
        border: 1px solid #ccc;
        text-align: center;
        border-collapse: collapse;
      }
      th {
        color: #fff;
        background-color: rgb(115, 210, 244);
      }
      th,
      td {
        width: 120px;
        height: 40px;
        font-size: 18px;
      }
      input {
        border: 1px solid #ccc;
      }
    </style>
  </head>

  <body>
    <table>
      <tr>
        <th><input type="checkbox" class="all" /><span>全选</span></th>
        <th>商品</th>
        <th>商家</th>
        <th>价格</th>
      </tr>
      <tr>
        <td><input type="checkbox" class="ck" /></td>
        <td>华为手机</td>
        <td>华为</td>
        <td>¥1999</td>
      </tr>
      <tr>
        <td><input type="checkbox" class="ck" /></td>
        <td>小米手机</td>
        <td>小米</td>
        <td>¥4999</td>
      </tr>
      <tr>
        <td><input type="checkbox" class="ck" /></td>
        <td>苹果手机</td>
        <td>苹果</td>
        <td>¥9999</td>
      </tr>
    </table>

    <script>
      let all = document.querySelector('.all')
      let span = document.querySelector('span')
      let ck = document.querySelectorAll('.ck')

      all.addEventListener('click', () => {
        console.log(all.checked)
        for (let i = 0; i < ck.length; i++) {
          ck[i].checked = all.checked
        }
        span.innerHTML = all.checked ? '取消' : '全选'
      })
    </script>
  </body>
</html>

(5)同时给多个元素绑定相同事件

HTML 复制代码
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>JS 事件</title>
    <style>
      table,
      tr,
      td,
      th {
        border: 1px solid #ccc;
        text-align: center;
        border-collapse: collapse;
      }
      th {
        color: #fff;
        background-color: rgb(115, 210, 244);
      }
      th,
      td {
        width: 120px;
        height: 40px;
        font-size: 18px;
      }
      input {
        border: 1px solid #ccc;
      }
    </style>
  </head>

  <body>
    <table>
      <tr>
        <th><input type="checkbox" class="all" /><span>全选</span></th>
        <th>商品</th>
        <th>商家</th>
        <th>价格</th>
      </tr>
      <tr>
        <td><input type="checkbox" class="ck" /></td>
        <td>华为手机</td>
        <td>华为</td>
        <td>¥1999</td>
      </tr>
      <tr>
        <td><input type="checkbox" class="ck" /></td>
        <td>小米手机</td>
        <td>小米</td>
        <td>¥4999</td>
      </tr>
      <tr>
        <td><input type="checkbox" class="ck" /></td>
        <td>苹果手机</td>
        <td>苹果</td>
        <td>¥9999</td>
      </tr>
    </table>

    <script>
      let all = document.querySelector('.all')
      let span = document.querySelector('span')
      let ck = document.querySelectorAll('.ck')

      all.addEventListener('click', () => {
        console.log(all.checked)
        for (let i = 0; i < ck.length; i++) {
          ck[i].checked = all.checked
        }
        span.innerHTML = all.checked ? '取消' : '全选'
      })

      for (let i = 0; i < ck.length; i++) {
        // 为元素绑定相同事件
        ck[i].addEventListener('click', () => {
          // console.log(ck[i].checked)
          // 点击任何一个小按钮,都要遍历所有的,查看是否有没被选中的
          for (let j = 0; j < ck.length; j++) {
            // 如果有没被选中的,就退出循环
            if (!ck[j].checked) {
              span.innerHTML = '全选'
              all.checked = false
              return
            }
          }

          // 循环结束说明都被选中了
          span.innerHTML = '取消'
          all.checked = true
        })
      }
    </script>
  </body>
</html> 

(6)购物车加减操作

需求:用户点击加号,文本框数值加1;点击减号,则减1,如果文本框的值为1,则减号禁用

HTML 复制代码
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>JS 事件</title>
    <style>
      * {
        box-sizing: border-box;
      }
      input {
        position: relative;
        width: 130px;
        height: 58px;
        border: 1px solid #ccc;
        outline: none;
        line-height: 58px;
        padding-left: 48px;
      }
      .add {
        position: absolute;
        top: 8px;
        left: 108px;
        width: 30px;
        height: 30px;
        background-color: #cad4d7;
        line-height: 30px;
        text-align: center;
        border: 1px solid #ccc;
      }
      .sub {
        position: absolute;
        top: 36px;
        left: 108px;
        width: 30px;
        height: 30px;
        background-color: #cad4d7;
        line-height: 30px;
        text-align: center;
        border: 1px solid #ccc;
      }
    </style>
  </head>

  <body>
    <input type="text" value="1" />
    <button class="add">+</button>
    <button class="sub" disabled>-</button>

    <script>
      let txt = document.querySelector('input')
      let add = document.querySelector('.add')
      let sub = document.querySelector('.sub')

      add.addEventListener('click', () => {
        txt.innerHTML = txt.value++
        sub.disabled =  false
      })

      sub.addEventListener('click', () => {
        txt.innerHTML = txt.value--
        sub.disabled = txt.value <= 1 ? true : false
      })
    </script>
  </body>
</html>

分析:

  • 获取表单元素、按钮元素;
  • 给按钮注册点击事件,获取表单的值;
  • 每点一次加号按钮,表单的数值就加1;
  • 每点一次减号按钮,则表单的数值减1,自减结束后,需要判断表单的值是否小于等于1,如果表单的值小于等于1,则减号按钮禁用
相关推荐
mldong7 小时前
你的 Vue3 项目也能有钉钉同款审批流设计器:npm 装包,10 分钟画出第一条审批流
前端·vue.js
2分钟速写快排7 小时前
什么是 RAG?如何用 RAG 实现一个用户记忆?
前端·后端·ai编程
passerby60618 小时前
如何自己造一个时间处理库
前端·javascript·github
走到天涯海角9 小时前
react里面的长列表渲染优化
前端·react.js·前端框架
小羊没烦恼!9 小时前
Hello Web API系列教程——Web API与国际化
java·服务器·前端·javascript·php
北岛贰9 小时前
迷茫焦虑期,我做了一个带支付带官网的 AI 聊天虚拟恋人 App
前端·人工智能·后端
mayaairi11 小时前
Vue2 组件通讯(三):全局事件总线、PubSub、插槽与组件实例属性
前端·javascript·vue.js
kyriewen11 小时前
面试官问我:AI 都能写代码了,前端凭什么还值 25K
前端·javascript·人工智能
风骏时光牛马12 小时前
AI源码分析:拆解模型底层实现逻辑
前端
BillKu12 小时前
全局样式变量:CSS 自定义属性(--border-color)和SCSS 变量($border-color)的说明
javascript·css·scss