纯js实现倒计时功能


Posted in Javascript onJanuary 06, 2017

通过js实现页面的倒计时功能。

思路: 传入一个秒数c,c/60可以得到分钟m, c%60可以得到显示的秒数s,同理,再将m/60可是得到小时数, m/%可以得到分钟数。通过setInterval每次将总秒数-1,并将计算所得时间显示到页面上。

第一版的肮脏代码如下, 可以作为反面教材思考一下

<html> 
  <head> 
    <title>Tomato</title> 
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 
    <script type="text/javascript"> 
      var vTimeLength = 5; 
      var vHour; 
      var vMinutes; 
      var vSeconds; 
      var vRemainingTime; 
      function countDown(){ 
        vTimeLength = vTimeLength - 1; 
        vMinutes = Math.floor(vTimeLength/60); 
        vSeconds = Math.floor(vTimeLength%60); 
        if (vMinutes >= 60){ 
          vHour = Math.floor(vMinutes/60); 
          var vMinutesNew = Math.floor(vMinutes%60); 
          vRemainingTime = vHour + ":" + vMinutesNew + ":" + vSeconds; 
        } else { 
          vRemainingTime = vMinutes + ":" + vSeconds; 
        } 
        document.getElementById("div_countDown").innerHTML = vRemainingTime; 
        if (vTimeLength < 1) { 
          alert('do sth'); 
        } 
      } 
    </script> 
  </head> 
  <body> 
    <div id="div_countDown"></div> 
    <script type="text/javascript"> 
      setInterval("countDown()", 1000); 
    </script> 
  </body> 
</html>

缺陷:

 1、定义了众多的全局变量,

 2、没有复用性,

 3、setInterval容易导致队列过多, 结束事件如果是非阻塞事件, 倒计时会继续执行出现负数,

 4、不符合面向对象思想。。。

针对缺陷1的解决方案是, 定义一个函数, 将相关全局变量放到函数内部,使之成为局部变量

针对缺陷2:为函数指定参数,提高复用性。 这里定义了3个参数vTimeLength为倒计时总秒数,showTagId为显示到页面元素的id, callback为倒计时结束后的回掉方法

针对缺陷3:用setTimeout替代setInterval

优化后的代码如下:

<html> 
  <head> 
    <title>countdown</title> 
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 
    <script type="text/javascript"> 
      function countDown(vTimeLength, showTagId, callback) { 
        var vHour; 
        var vMinutes; 
        var vMinutesNew 
        var vSeconds; 
        var vRemainingTime; 
        function countDownInner(vTimeLength){ 
          vMinutes = Math.floor(vTimeLength/60); 
          vSeconds = Math.floor(vTimeLength%60); 
          if (vMinutes >= 60){ 
            vHour = Math.floor(vMinutes/60); 
            vMinutesNew = Math.floor(vMinutes%60); 
            vRemainingTime = vHour + ":" + vMinutesNew + ":" + vSeconds; 
          } else { 
            vRemainingTime = vMinutes + ":" + vSeconds; 
          } 
          document.getElementById(showTagId).innerHTML = vRemainingTime; 
          vTimeLength = vTimeLength - 1; 
          if (vTimeLength > 0) { 
            setTimeout(function(){countDownInner(vTimeLength);}, 1000); 
          } else { 
            callback(); 
          } 
        } 
        countDownInner(vTimeLength); 
      } 
    </script> 
  </head> 
  <body> 
    <div id="div_countDown"></div> 
    <script type="text/javascript"> 
      countDown(5, "div_countDown", function(){alert('do sth');}); 
    </script> 
  </body> 
</html>

这里有一点需要注意

setTimeout(function(){countDownInner(vTimeLength);}, 1000); 

第一次我将此句写成了

setTimeout(countDownInner(vTimeLength), 1000); 

结果函数直接执行了, 没有等待1秒的时间。如果没有入参, 即setTimeout("countDownInner()", 1000); 则可正常执行。

至于前面提到的不够面向对象的缺陷, 也是刚刚接触, 这里贴出代码,希望能够互相交流

<html> 
  <head> 
    <title>count_down</title> 
    <script type="text/javascript"> 
    var countDown = { 
      flag: true,  
      hour: 0, 
      minutes: 0, 
      minutesNew: 0, 
      seconds: 0, 
      show: 0, 
      current: 0, 
      length: 0, 
      showTagId: null, 
      // callback: null, 
      countDownInner: function(vTimeLength){ 
        if (!this.flag) { 
          return; 
        } 
        var that=this; 
        this.current = vTimeLength; 
        minutes = Math.floor(vTimeLength/60); 
        seconds = Math.floor(vTimeLength%60); 
        if (minutes >= 60){ 
          hour = Math.floor(minutes/60); 
          minutesNew = Math.floor(minutes%60); 
          show = hour + ":" + minutesNew + ":" + seconds; 
        } else { 
          show = minutes + ":" + seconds; 
        } 
        document.getElementById(this.showTagId).innerHTML = show; 
        vTimeLength = vTimeLength - 1; 
        if (vTimeLength > 0) { 
          setTimeout(function(){that.countDownInner(vTimeLength);}, 1000); 
        } else { 
          setTimeout(function(){that.callback();}, 1000); 
        } 
      }, 
      run: function(vTimeLength, showTagId, callback) { 
        if (!this.flag) { 
          this.flag = true; 
          this.countDownInner(this.current); 
        } else if (showTagId) { 
          this.length = vTimeLength; 
          this.showTagId = showTagId; 
          this.callback = callback; 
          this.countDownInner(vTimeLength);   
        } 
      }, 
      stop: function(){ 
        this.flag = false; 
      },  
      restart: function(){ 
        this.flag = true; 
        this.countDownInner(this.length); 
      } 
    }; 
    function countDownStart() { 
      countDown.run(); 
    } 
    function countDownStop() { 
      countDown.stop(); 
    } 
    </script> 
  </head> 
  <body> 
    <div id="div_countDown"></div> 
    <script type="text/javascript"> 
      countDown.run(5, 'div_countDown',function(){alert('12')}); 
    </script> 
    <span> 
      <button onclick="countDownStart();">start</button> 
      <button onclick="countDownStop();">stop</button> 
    </span> 
  </body> 
</html>

一个难点是this的使用, 在函数内部, this是调用当前函数范围,所以setTimeout(function(){this.countDownInner(vTimeLength);}, 1000);会出现undefined。

解决方案是定义一个that变量接收外部函数的this指针,然后通过that即可调用外部域。

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持三水点靠木!

Javascript 相关文章推荐
用JavaScrpt实现文件夹简单轻松加密的实现方法图文
Sep 08 Javascript
jquery $.ajax()取xml数据的小问题解决方法
Nov 20 Javascript
JavaScript中的typeof操作符用法实例
Apr 05 Javascript
一个通过script自定义属性传递配置参数的方法
Sep 15 Javascript
javascript创建对象的几种模式介绍
May 06 Javascript
H5图片压缩与上传实例
Apr 21 Javascript
javascript实现二叉树遍历的代码
Jun 08 Javascript
浅谈vue中慎用style的scoped属性
Nov 28 Javascript
vue组件tabbar使用方法详解
Nov 06 Javascript
9102了,你还不会移动端真机调试吗
Mar 25 Javascript
JS PHP字符串截取函数实现原理解析
Aug 29 Javascript
在vue中获取wangeditor的html和text的操作
Oct 23 Javascript
JS正则截取两个字符串之间及字符串前后内容的方法
Jan 06 #Javascript
微信小程序开发教程-手势解锁实例
Jan 06 #Javascript
jQuery ajax的功能实现方法详解
Jan 06 #Javascript
详解JS中定时器setInterval和setTImeout的this指向问题
Jan 06 #Javascript
Jqprint实现页面打印
Jan 06 #Javascript
JS使用正则截取两个字符串之间的字符串实现方法详解
Jan 06 #Javascript
jQuery EasyUi 验证功能实例解析
Jan 06 #Javascript
You might like
在PHP中使用curl_init函数的说明
2010/11/02 PHP
PHP实现读取文件夹及批量重命名文件操作示例
2019/04/15 PHP
基于JQuery框架的AJAX实例代码
2009/11/03 Javascript
js 回车提交表单两种实现方法
2012/12/31 Javascript
鼠标放在图片上显示大图的JS代码
2013/03/26 Javascript
基于jQuery选择器的整理集合
2013/04/26 Javascript
js替代copy(示例代码)
2013/11/27 Javascript
Javascript的严格模式strict mode详细介绍
2014/06/06 Javascript
escape编码与unescape解码汉字出现乱码的解决方法
2014/07/02 Javascript
JavaScript中数组继承的简单示例
2015/07/29 Javascript
jquery实现的判断倒计时是否结束代码
2016/02/05 Javascript
jQuery简单设置文本框回车事件的方法
2016/08/01 Javascript
JavaScript Ajax实现异步通信
2016/12/14 Javascript
微信小程序开发中的疑问解答汇总
2017/07/03 Javascript
d3.js实现自定义多y轴折线图的示例代码
2018/05/30 Javascript
浅析JS中回调函数及用法
2018/07/25 Javascript
javascript中undefined的本质解析
2019/07/31 Javascript
vue中使用element ui的弹窗与echarts之间的问题详解
2019/10/25 Javascript
ant design实现圈选功能
2019/12/17 Javascript
Python实现二叉堆
2016/02/03 Python
深入浅析Python的类
2018/06/22 Python
python opencv实现运动检测
2018/07/10 Python
对python制作自己的数据集实例讲解
2018/12/12 Python
python使用selenium登录QQ邮箱(附带滑动解锁)
2019/01/23 Python
PyQt5 实现字体大小自适应分辨率的方法
2019/06/18 Python
解决阿里云邮件发送不能使用25端口问题
2020/08/07 Python
英国第一摩托车和摩托车越野配件商店:GhostBikes
2019/03/10 全球购物
陈欧广告词
2014/03/14 职场文书
大学自主招生推荐信
2014/05/10 职场文书
党支部鉴定意见
2015/06/02 职场文书
五星红旗迎风飘扬观后感
2015/06/17 职场文书
元宵节晚会主持词
2015/07/01 职场文书
听证会主持词
2015/07/03 职场文书
OpenCV全景图像拼接的实现示例
2021/06/05 Python
使用Mysql计算地址的经纬度距离和实时位置信息
2022/04/29 MySQL
python读取mat文件生成h5文件的实现
2022/07/15 Python