6.1 JavaScript Apis - 定时器、事件监听、鼠标事件、键盘事件

发布于:2024-12-18 ⋅ 阅读:(94) ⋅ 点赞:(0)

JavaScript Apis -定时器、事件监听、鼠标事件、键盘事件

一、间歇函数

定时器有两种,今天先看间歇函数

1.1 介绍

  • 开始定时器
setInterval(函数,间隔时间)

作用:每隔一段时间就会调用这个函数

间隔时间单位是毫秒

<script>
  setInterval(function() {
    console.log("间歇函数执行了")
  },1000)
</script>

注意

定时器返回的是一个id数字,每一个定时器都是独一无二的

fuction fn(){
    console.log('一秒执行一次')
}
// 注意这里没有加小括号,如果加了小括号fn()表示调用的意思
setInterval(fn,1000)
//setInterval('fn()',1000) 如果一定要加小括号的话可以这么写,但是一般不这么写
  • 关闭定时器
let 变量名=setInterval(函数,间隔时间)
clearInterval(变量名)

1.2 倒计时效果

案例:阅读注册协议

需求:按钮60s之后才可以使用

分析

  1. 开始先把按钮禁用(disabled属性)

  2. 一定要获取元素

  3. 函数内部处理逻辑

    秒数开始减减

    按钮里面的文字跟着一起变化

    如果秒数等于0,停止定时器,里面文字变为同意,最后按钮可以点击

<body>
<textarea name="" id="" cols="30" rows="10">
        用户注册协议
        欢迎注册成为京东用户!在您注册过程中,您需要完成我们的注册流程并通过点击同意的形式在线签署以下协议,请您务必仔细阅读、充分理解协议中的条款内容后再点击同意(尤其是以粗体或下划线标识的条款,因为这些条款可能会明确您应履行的义务或对您的权利有所限制)。
        【请您注意】如果您不同意以下协议全部或任何条款约定,请您停止注册。您停止注册后将仅可以浏览我们的商品信息但无法享受我们的产品或服务。如您按照注册流程提示填写信息,阅读并点击同意上述协议且完成全部注册流程后,即表示您已充分阅读、理解并接受协议的全部内容,并表明您同意我们可以依据协议内容来处理您的个人信息,并同意我们将您的订单信息共享给为完成此订单所必须的第三方合作方(详情查看
    </textarea>
<br>
<button class="btn" disabled>我已经阅读用户协议(5)</button>
<script>
  //1.获取元素
  const btn = document.querySelector('.btn')
  console.log(btn.innerHTML)//这个表单button比较特殊,是个双标签,不是使用value获取的(之前input是单标签,使用value获取的),是使用innerHTML获取的
  //2.倒计时
  let i = 5
  // 2.1开启定时器
  var interval = setInterval(function() {
    i--
    btn.innerHTML = `我已经阅读用户协议(${i})`
    if (i === 0) {
      //关闭定时器
      clearInterval(interval)
      btn.disabled = false
      btn.innerHTML = '同意'
    }
  }, 1000)
  
</script>

</body>

二、事件

2.1 添加事件监听

事件是在编程时系统内发生的动作或者发生的事情

比如用户在网页上单击一个按钮

事件监听:让程序检测是否有事件产生,一旦有事件触发,就立即调用一个函数做出响应,也称为绑定事件或者注册事件,比如鼠标经过显示下拉菜单,比如点击可以播放轮播图等

也称之为注册事件

语法

元素对象.addEventListener('事件类型',要执行的函数)

事件监听的三要素

  • 事件源:那个dom元素被事件触发了,要获取dom元素
  • 事件类型:用什么方式触发,比如鼠标单击click、鼠标经过mouseover等
  • 事件调用的函数:要做什么事情

事件监听的版本

  • DOM L0

    事件源.on事件=function(){}

  • DOM L2

    事件源.addEventListener(事件,事件处理函数)

我们现在使用的是这个版本的事件监听

  • 区别

    on方式会被覆盖,addEventListener方式可绑定多次,拥有事件更多特性,推荐使用

示例:点击了按钮,弹出一个对话框

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>
<button>点击</button>
<script>
  //需求“点击了按钮,弹出一个对话框
  //1.事件源 按钮
  const btn = document.querySelector('button')
  //2.事件类型 点击鼠标
  //3.事件处理程序,弹出对话框
  btn.addEventListener('click',function(){
    alert('你好呀')
  })

</script>
</body>
</html>

示例:点击叉号,关闭广告

<body>
    <div class = "box">
        我是广告
        <div class="close">X</div>
    </div>
<script>
  //1.事件源 
  const close = document.querySelector('.close')
  const box = document.querySelector('.box') //大盒子
  //2.事件监听
  close.addEventListener('click',function(){
    box.style.display = 'none' //隐藏,关闭了广告
  })
</script>
    
</body>

2.2 事件类型

image-20240717221843049

2.2.1 鼠标事件

click 鼠标点击

mouseenter 鼠标经过

mouseleave 鼠标离开

  • mouseover和mouseout会有冒泡效果
  • mouseenter和mouseleave没有冒泡效果,推荐使用这两个
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<style>
    div {
        width: 200px;
        height: 200px;
        background-color: pink;
    }
</style>
<body>
<div></div>
<script>
  const div = document.querySelector('div')
  //鼠标经过
  div.addEventListener('mouseenter', function() {
    console.log('鼠标经过')
  })
  //鼠标离开
  div.addEventListener('mouseleave', function() {
    console.log('鼠标离开')
  })
</script>
</body>
</html>

2.2.2 焦点事件

焦点事件,一般用于表单获得或者失去焦点

focus 获得焦点

blur 失去焦点

<body>
<input type="text">
<script>
  const input = document.querySelector('input')
  //获得焦点
  input.addEventListener('focus',function(){
    console.log('有焦点触发')
  })
  //失去焦点
  input.addEventListener('blur',function(){
    console.log('失去焦点触发')
  })
</script>

</body>

比如,失去光标的话,不存在搜索框

image-20240719164808310

假如说存在光标的话,下面就会出现一些建议搜索的信息

image-20240719164841940

实现这个小案例

<!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>
      * {
          margin: 0;
          padding: 0;
          box-sizing: border-box;
      }

      ul {

          list-style: none;
      }

      .mi {
          position: relative;
          width: 223px;
          margin: 100px auto;
      }

      .mi input {
          width: 223px;
          height: 48px;
          padding: 0 10px;
          font-size: 14px;
          line-height: 48px;
          border: 1px solid #e0e0e0;
          outline: none;
      }

      .mi .search {
          border: 1px solid #ff6700;
      }

      .result-list {
          display: none;
          position: absolute;
          left: 0;
          top: 48px;
          width: 223px;
          border: 1px solid #ff6700;
          border-top: 0;
          background: #fff;
      }

      .result-list a {
          display: block;
          padding: 6px 15px;
          font-size: 12px;
          color: #424242;
          text-decoration: none;
      }

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

</head>

<body>
<div class="mi">
    //注意,这个地方的search不是class是type
  <input type="search" placeholder="小米笔记本">
  <ul class="result-list">
    <li><a href="#">全部商品</a></li>
    <li><a href="#">小米11</a></li>
    <li><a href="#">小米10S</a></li>
    <li><a href="#">小米笔记本</a></li>
    <li><a href="#">小米手机</a></li>
    <li><a href="#">黑鲨4</a></li>
    <li><a href="#">空调</a></li>
  </ul>
</div>
<script>
  //1.获取元素
  // const input = document.querySelector('input')
  const input = document.querySelector('[type=search]') //也可以这么写,属性选择器
  const ul = document.querySelector('.result-list')

  //2.监听时间获得焦点
  input.addEventListener('focus', function() {
    console.log('有焦点触发')
    ul.style.display = 'block'//显示
    //将文本框添加 .search样式
    input.classList.add('search')
  })

  //3.失去焦点
  input.addEventListener('blur', function() {
    console.log('失去焦点触发')
    ul.style.display = 'none'//取消显示
    input.classList.remove('search')
  })

</script>
</body>

</html>

2.2.3 键盘事件

keydown 按下键盘

keydown 键盘弹起

<body>
<input type="text">
<script>
  const input = document.querySelector('input')
  input.addEventListener('keydown',function(){
    console.log('键盘按下')
  })
  input.addEventListener('keydown',function(){
    console.log('键盘弹起')
  })
  input.addEventListener('input',function(){
    console.log('用户输入文本事件')
  })
</script>
</body>

2.2.4 文本事件

<body>
<input type="text">
<script>
  const input = document.querySelector('input')

  input.addEventListener('input',function(){
    console.log('用户输入文本事件')
  })
</script>
</body>

检测用户输入的字数

<!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>
      .wrapper {
          min-width: 400px;
          max-width: 800px;
          display: flex;
          justify-content: flex-end;
      }

      .avatar {
          width: 48px;
          height: 48px;
          border-radius: 50%;
          overflow: hidden;
          background: url(./images/avatar.jpg) no-repeat center / cover;
          margin-right: 20px;
      }

      .wrapper textarea {
          outline: none;
          border-color: transparent;
          resize: none;
          background: #f5f5f5;
          border-radius: 4px;
          flex: 1;
          padding: 10px;]
          /*过渡的样式*/
          transition: all 0.5s;
          height: 30px;
      }

      .wrapper textarea:focus {
          border-color: #e4e4e4;
          background: #fff;
          height: 50px;
      }

      .wrapper button {
          background: #00aeec;
          color: #fff;
          border: none;
          border-radius: 4px;
          margin-left: 10px;
          width: 70px;
          cursor: pointer;
      }

      .wrapper .total {
          margin-right: 80px;
          color: #999;
          margin-top: 5px;
          opacity: 0;
          transition: all 0.5s;
      }

      .list {
          min-width: 400px;
          max-width: 800px;
          display: flex;
      }

      .list .item {
          width: 100%;
          display: flex;
      }

      .list .item .info {
          flex: 1;
          border-bottom: 1px dashed #e4e4e4;
          padding-bottom: 10px;
      }

      .list .item p {
          margin: 0;
      }

      .list .item .name {
          color: #FB7299;
          font-size: 14px;
          font-weight: bold;
      }

      .list .item .text {
          color: #333;
          padding: 10px 0;
      }

      .list .item .time {
          color: #999;
          font-size: 12px;
      }
  </style>
</head>

<body>
<div class="wrapper">
  <i class="avatar"></i>
  <textarea id="tx" placeholder="发一条友善的评论" rows="2" maxlength="200"></textarea>
  <button>发布</button>
</div>
<div class="wrapper">
  <span class="total">0/200</span>
</div>
<div class="list">
  <div class="item" style="display: none;">
    <i class="avatar"></i>
    <div class="info">
      <p class="name">清风徐来</p>
      <p class="text">大家都辛苦啦,感谢各位大大的努力,能圆满完成真是太好了[笑哭][支持]</p>
      <p class="time">2022-10-10 20:29:21</p>
    </div>
  </div>
</div>

<script>
  const tx = document.querySelector('#tx')
  const total = document.querySelector('.total')
  //1.当我们文本域获得了焦点,就让total显示出来
  tx.addEventListener('focus',function(){
    total.style.opacity = 1
  })
  //2.当我们文本域失去了焦点,就让total显示出来
  tx.addEventListener('blur',function(){
    total.style.opacity = 0
  })
  //3.检测用户输入
  tx.addEventListener('input',function(){
    total.innerHTML =`${tx.value.length}/200字`
  })

</script>
</body>
</html>

2.3 事件对象 event

事件对象

  • 这个对象里有事件触发时的相关信息

鼠标点击点击事件中,事件对象就存了鼠标点在哪个位置等信息

使用场景

可以判断用户按下哪个键,比如按下回车键可以发布新闻

可以判断鼠标点击了哪个元素,从而做相应的操作

语法

在事件绑定的回调函数的第一个参数就是事件对象

一般命名为event、ev、e

  元素.addEventListener('click',function(e){
    ....
  })
<body>
<button>点击</button>

<script>
  const btn = document.querySelector('button')
  btn.addEventListener('click', function(e) {
    //输出了点击对象
    console.log(e)
  })
</script>
</body>

部分常用属性

type获取当前的事件类型

clientX/clientY获取光标相对于浏览器可见窗口左上角的位置

offsetX/offsetY获取光标相对于当前DOM元素左上角的位置

key:用户按下的键盘键的值,现在已经不提倡使用keyCode

image-20240722151449052

<script>
  const btn = document.querySelector('button')
  btn.addEventListener('click', function(e) {
    //输出了点击对象
    console.log(e)
    console.log(e.key)
    if (e.key === 'Enter'){
      console.log("按了回车键")
    }
  })
</script>
</body>

2.3.1 回车发布评论案例

需求:按下回车键,可以发布信息

分析

  • 按下键盘事件keydown或者keyup都可以
  • 如果用户按下的是回车键盘,则发布信息
  • 让留言信息模块显示,把拿到的数据渲染到对应标签内部
<!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>
      .wrapper {
          min-width: 400px;
          max-width: 800px;
          display: flex;
          justify-content: flex-end;
      }

      .avatar {
          width: 48px;
          height: 48px;
          border-radius: 50%;
          overflow: hidden;
          background: url(./images/avatar.jpg) no-repeat center / cover;
          margin-right: 20px;
      }

      .wrapper textarea {
          outline: none;
          border-color: transparent;
          resize: none;
          background: #f5f5f5;
          border-radius: 4px;
          flex: 1;
          padding: 10px;
      ]
          /*过渡的样式*/
      transition: all 0.5 s;
          height: 30px;
      }

      .wrapper textarea:focus {
          border-color: #e4e4e4;
          background: #fff;
          height: 50px;
      }

      .wrapper button {
          background: #00aeec;
          color: #fff;
          border: none;
          border-radius: 4px;
          margin-left: 10px;
          width: 70px;
          cursor: pointer;
      }

      .wrapper .total {
          margin-right: 80px;
          color: #999;
          margin-top: 5px;
          opacity: 0;
          transition: all 0.5s;
      }

      .list {
          min-width: 400px;
          max-width: 800px;
          display: flex;
      }

      .list .item {
          width: 100%;
          display: flex;
      }

      .list .item .info {
          flex: 1;
          border-bottom: 1px dashed #e4e4e4;
          padding-bottom: 10px;
      }

      .list .item p {
          margin: 0;
      }

      .list .item .name {
          color: #FB7299;
          font-size: 14px;
          font-weight: bold;
      }

      .list .item .text {
          color: #333;
          padding: 10px 0;
      }

      .list .item .time {
          color: #999;
          font-size: 12px;
      }
  </style>
</head>

<body>
<div class="wrapper">
  <i class="avatar"></i>
  <textarea id="tx" placeholder="发一条友善的评论" rows="2" maxlength="200"></textarea>
  <button>发布</button>
</div>
<div class="wrapper">
  <span class="total">0/200</span>
</div>
<div class="list">
  <div class="item" style="display: none;">
    <i class="avatar"></i>
    <div class="info">
      <p class="name">清风徐来</p>
      <p class="text">大家都辛苦啦,感谢各位大大的努力,能圆满完成真是太好了[笑哭][支持]</p>
      <p class="time">2022-10-10 20:29:21</p>
    </div>
  </div>
</div>

<script>
  const tx = document.querySelector('#tx')
  const total = document.querySelector('.total')
  const item = document.querySelector('.item')
  const text = document.querySelector('.text')
  //1.当我们文本域获得了焦点,就让total显示出来
  tx.addEventListener('focus', function() {
    total.style.opacity = 1
  })
  //2.当我们文本域失去了焦点,就让total显示出来
  tx.addEventListener('blur', function() {
    total.style.opacity = 0
  })
  //3.检测用户输入
  tx.addEventListener('input', function() {
    total.innerHTML = `${tx.value.length}/200字`
  })
  //4.按下回车,发布评论
  tx.addEventListener('keyup', function(e) {
    //只有按下的事回车键,才会触发送评论
    if (e.key === 'Enter' && tx.value.trim() !== '') {
      item.style.display = 'block'
      text.innerHTML = tx.value
      //清空文本域的内容
      tx.value = ''
      total.innerHTML = `0/200字`
    }
  })
</script>

</body>

</html>

2.4 环境对象

能够分析判断函数运行在不同环境中this所指代的对象

环境对象:值的是函数内部特殊的变量this,代表着当前函数运行时所处的环境

作用:弄清楚this的指向,可以让我们的代码更简洁

函数的调用方式不同,this指代的对象也不同

“谁调用,this就指代谁”,是判断this指向的粗略规则

2.5 回调函数

如果函数A做为参数传递给参数B时,我们称函数A为回调函数

常见的使用场景:

function fn(){
    console.log('我是回调函数...')
}
//fn传递给了setInterval,fn就是回调函数
setInterval(fn,1000)

2.6 综合案例

2.6.1 tab 切换

需求:鼠标经过不同的选项卡,底部可以显示不同的内容

分析

  • 主要核心是类的切换,设定一个当前类,可以让当前元素高亮
  • 鼠标经过当前选项卡,先移除其余元素身上的当前类,而只给当前元素添加类
  • 注意!当前类只能有一个

image-20240722172046660

其实相当于三个模块,每次只展示一个模块,剩下的模块进行隐藏

image-20240722180730501

<!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>tab栏切换</title>
  <style>
      * {
          margin: 0;
          padding: 0;
      }

      .tab {
          width: 590px;
          height: 340px;
          margin: 20px;
          border: 1px solid #e4e4e4;
      }

      .tab-nav {
          width: 100%;
          height: 60px;
          line-height: 60px;
          display: flex;
          justify-content: space-between;
      }

      .tab-nav h3 {
          font-size: 24px;
          font-weight: normal;
          margin-left: 20px;
      }

      .tab-nav ul {
          list-style: none;
          display: flex;
          justify-content: flex-end;
      }

      .tab-nav ul li {
          margin: 0 20px;
          font-size: 14px;
      }

      .tab-nav ul li a {
          text-decoration: none;
          border-bottom: 2px solid transparent;
          color: #333;
      }

      .tab-nav ul li a.active {
          border-color: #e1251b;
          color: #e1251b;
      }

      .tab-content {
          padding: 0 16px;
      }

      .tab-content .item {
          display: none;
      }

      .tab-content .item.active {
          display: block;
      }
  </style>
</head>

<body>
<div class="tab">
  <div class="tab-nav">
    <h3>每日特价</h3>
    <ul>
      <li><a class="active" href="javascript:;">精选</a></li>
      <li><a href="javascript:;">美食</a></li>
      <li><a href="javascript:;">百货</a></li>
      <li><a href="javascript:;">个护</a></li>
      <li><a href="javascript:;">预告</a></li>
    </ul>
  </div>
  <div class="tab-content">
    <div class="item active"><img src="./images/tab00.png" alt=""/></div>
    <div class="item"><img src="./images/tab01.png" alt=""/></div>
    <div class="item"><img src="./images/tab02.png" alt=""/></div>
    <div class="item"><img src="./images/tab03.png" alt=""/></div>
    <div class="item"><img src="./images/tab04.png" alt=""/></div>
  </div>
</div>

<script>
  //1.a模块制作,要给5个链接绑定鼠标经过事件
  //1.1 获取a元素 注意,这个地方获取的时候,一定要填写all
  const as = document.querySelectorAll('.tab-nav a') //返回值其实是一个数组,因为我们获取的事tab-nav类中的a标签
  //1.2 给每个a元素都绑定上鼠标经过事件
  for (let i = 0; i < as.length; i++) {
    console.log(as)
    as[i].addEventListener('mouseenter',function(){
      console.log('鼠标经过')
      //先将其他a标签的active类移除,删除高亮效果
      document.querySelector('.tab-nav .active').classList.remove('active')
      //当前经过的a标签的高亮样式
      //this就是当前的a标签
      this.classList.add('active')

      //下面的数据进行一一对应
      //删除下面盒子的active样式
      document.querySelector('.tab-content .active').classList.remove('active')
      //对应序号的item类显示 也就是添加active类
      document.querySelector(`.tab-content .item:nth-child(${i+1})`).classList.add('active')
    })
  }
</script>
</body>
</html>

2.6.2 表单全选反选

需求1:用户点击全选,则下面复选框全部选择,取消全选则全部取消

分析

  • 全选复选框点击,可以得到当前按钮checked
  • 把下面所有的小复选框checked,改为和全选复选框一致

image-20240722185031787

需求2:用户全部勾选小复选框后,全选复选框也会默认勾选

  • 遍历下面的所有checkbox,添加点击事件
  • 检查小复选框中的个数,是不是等于小复选框总的个数
  • 把结果给全选按钮
  • 利用css复选框选择器input:checked
<!DOCTYPE html>

<html>

<head lang="en">
  <meta charset="UTF-8">
  <title></title>
  <style>
      * {
          margin: 0;
          padding: 0;
      }

      table {
          border-collapse: collapse;
          border-spacing: 0;
          border: 1px solid #c0c0c0;
          width: 500px;
          margin: 100px auto;
          text-align: center;
      }

      th {
          background-color: #09c;
          font: bold 16px "微软雅黑";
          color: #fff;
          height: 24px;
      }

      td {
          border: 1px solid #d0d0d0;
          color: #404060;
          padding: 10px;
      }

      .allCheck {
          width: 80px;
      }

      /*这个样式的意思是选择被勾选的复选框,当我们被勾选后,复选框的大小会发生变化  ck是类名  checked是属性*/
      /*:checked 的意思是被勾选的复选框*/
      .ck:checked {
          width: 20px;
          height: 20px;
      }
  </style>
</head>

<body>
<table>
  <tr>
    <th class="allCheck">
      <input type="checkbox" name="" id="checkAll"> <span class="all">全选</span>
    </th>
    <th>商品</th>
    <th>商家</th>
    <th>价格</th>
  </tr>
  <tr>
    <td>
      <input type="checkbox" name="check" class="ck">
    </td>
    <td>小米手机</td>
    <td>小米</td>
    <td>1999</td>
  </tr>
  <tr>
    <td>
      <input type="checkbox" name="check" class="ck">
    </td>
    <td>小米净水器</td>
    <td>小米</td>
    <td>4999</td>
  </tr>
  <tr>
    <td>
      <input type="checkbox" name="check" class="ck">
    </td>
    <td>小米电视</td>
    <td>小米</td>
    <td>5999</td>
  </tr>
</table>
<script>
  //1.获取大复选框
  const checkAll = document.querySelector('#checkAll')//id选择器
  //2.获取所有的小复选框
  const cks = document.querySelectorAll('.ck')
  //3.点击大复选框
  checkAll.addEventListener('click', function() {
    //得到当前大复选框的选中状态 true:目前是选中状态 false:目前是未选中状态
    console.log(checkAll.checked)
    //4.遍历所有的小复选框,让小复选框的checked=大复选框的checked
    for (let i = 0; i < cks.length; i++) {
      cks[i].checked = checkAll.checked
    }
  })
  //5.小复选框控制大复选框
  //5.1给每个小复选框添加点击事件
  for (let i = 0; i < cks.length; i++) {
    cks[i].addEventListener('click', function() {
      //判断选中的小复选框的个数是不是等于总的小复选框的个数
        checkAll.checked = document.querySelectorAll('.ck:checked').length === cks.length
    })
  }
</script>
</body>
</html>

网站公告

今日签到

点亮在社区的每一天
去签到