定时器的知识

+ 在前端 JS 内的代码执行是单线程(同一个时间内只能做一件事情)

+ JS 提供给我们一个 异步代码执行机制(定时器)

+ 异步代码执行机制(EventLoop)

=> 当代码执行过程中, 遇到异步代码了

=> 会把异步代码放在 事件队列池 中等待

=> 继续向后执行同步代码

=> 等到所有同步代码执行完毕, 调用栈空的时候, 再去异步事件队列池内拿到异步代码执行(先进先出)

定时器的开启(设置)

1. 延时定时器(炸弹定时器)

=> 语法: setTimeout(函数, 数字)

-> 函数: 表示时间到达的时候要执行的代码

-> 数字: 倒计时的时间(单位是 ms)

2. 间隔定时器

=> 语法: setInterval(函数, 数字)

-> 函数: 表示每间隔一段时间以后执行的代码

-> 数字: 间隔的时间(单位是 ms)

定时器的返回值

+ 两种定时器的返回值是一样的

+ 不区分定时器种类, 只是表示你是页面上的第几个定时器

关闭定时器(销毁)

+ 销毁定时器的时候, 不区分定时器种类, 只要给出的定时器数字是对的, 就可以销毁

+ 语法:

=> clearTimeout()

=> cleatInterval()

*/

// 1. 延时定时器

// 2000ms 以后会执行 a 这个函数

// console.log(new Date())

// setTimeout(function a() {

// console.log('boom')

// console.log(new Date())

// }, 2000)

// 2. 间隔定时器

// setInterval(function () {

// console.log(new Date())

// }, 1000)


 

// 定时器的返回值

// var t1 = setTimeout(function () {})

// var t2 = setInterval(function () {})

// console.log('t1 : ', t1)

// console.log('t2 : ', t2)
 

// 关闭定时器

var t1 = setTimeout(function () { console.log('timeout') }, 3000)

var t2 = setInterval(function () { console.log('interval') }, 1000)

// 点击按钮关闭定时器

// btn 表示页面中 id 为 btn 的元素

// onclick 表示点击在这个元素身上的时候, 执行后面的函数

btn.onclick = function () {

// 执行关闭定时器的代码

// clearTimeout(t1)

// clearTimeout(t2)

clearInterval(t1)

clearInterval(t2)

}

                                       案例:倒计时

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <style>
    * {
      margin: 0;
      padding: 0;
    }
    body {
      background-color: #ccc;
    }
    div {
      width: 300px;
      height: 80px;
      background-color: #ccc;
      line-height: 40px;
      text-align: center;
      color: red;
      text-shadow: -1px -1px 0 #ccc, 1px 1px 0 #fff;
    }
  </style>
</head>
<body>

  <div>
    <p>距离出去浪还有: </p>
    <span id="timeBox"> 00 天 00 小时 00 分 00 秒</span>
  </div>

  <script src="./utils.js"></script>
  <script>
    /*
      倒计时

        + 每间隔 1s 拿到一次当前时间和目标时间之间的时间差
          => 间隔定时器
            -> 当前时间
        + 直接获取到目标时间
    */

    // 1. 拿到目标时间
    var target = new Date('2022-3-1 17:18:30')


    // 2. 开启定时器
    var timer = setInterval(function () {
      // 3. 在定时器内拿到当前时间
      var current = new Date()

      // 4. 拿到每一次的时间差
      var diff = diffTime(current, target)

      // 5. 写入页面
      // 元素.innerText = 值
      // 向一个标签内写入文本, 当你写入第二个文本的时候, 会覆盖第一个
      timeBox.innerText = ` ${ diff.day } 天 ${ diff.hours } 小时 ${ diff.minutes } 分 ${ diff.seconds } 秒`

      // 6. 关闭定时器
      // 当四个值都是 0 的时候, 关闭定时器
      if (diff.day === 0 && diff.hours === 0 && diff.minutes === 0 && diff.seconds === 0) clearInterval(timer)
    }, 1000)

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

效果:

                                案例分析:

+ 问题1: 什么时候会出现效果 ? 点击的时候

=> 所有的代码书写在点击事件内

+ 问题2: 在点击事件内根据时间开启定时器, 开启哪一个定时器 ?

=> 间隔定时器, 因为需要每间隔 1s 修改一次

=> 点击的时候, 只是开启一个定时器吗 ?

=> 60s 以后要关闭

=> 点击的瞬间, 会在 1s 以后, 才会出现第一次效果

=> 点击的瞬间, 应该先修改一次文本

// 3. 全局准备一个开关

var flag = true

// 1. 给 页面中 id="btn" 的按钮添加一个点击事件

btn.onclick = function () {

// 3-2. 判断开关是否是开启的

if (!flag) return

// 3-3. 关闭开关

flag = false

// 2. 开启定时器

// 2-1. 需要在开启定时器以前, 提前设置一次文本

btn.innerText = '再次获取(5s)'

// 2-2. 提前准备一个变量, 表示倒计时的总时间(注意: 书写在定时器外面)

var s = 4

var timer = setInterval(function () {

// 2-3. 修改 button 按钮内的文本

btn.innerText = `再次获取(${ s-- }s)`

// 2-4. 当 s 倒计时到达 0 的时候, 关闭定时器

if (s < 0) {

clearInterval(timer)

// 文本回归

btn.innerText = '点击获取验证码'

// 3-4. 再次开启开关

flag = true

}

}, 1000)

}

/*

分析问题出现的原因

+ 因为所有内容都书写在点击事件内

+ 我们每一次的点击都会执行一遍点击事件内的所有代码

+ 点击事件内的代码执行一次, 就会开启一个定时器

+ 当你多次点击的时候, 会不停的开启定时器, 多个定时器并行

解决方向

+ 当你点击的时候, 开启倒计时

+ 在本次倒计时结束以前, 所有的点击没有效果

+ 只要事件函数内的代码执行, 就会开启一个倒计时

+ 核心: 不让点击事件内的代码执行

+ 如何能让事件内的代码不执行 ?

=> return

=> 因为是一个函数, 只要执行了 return, 后续代码都不执行了

+ 解决频繁 DOM 操作的技能 ?

=> 开关

=> 在全局定义一个开关, 设置为 true

=> 在事件内判断 如果 开关是 true, 那么代码执行

=> 如果开始是 false, 代码直接 return

=> 当你点击的时候

-> 不光要开启定时器, 还在在开启定时器的时候把开关关闭

-> 等到关闭定时器的时候, 表示本次倒计时结束了, 此时再次打开开关, 表示可以进行下一次点击了

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我是打工人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值