纯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 相关文章推荐
通过jquery还原含有rowspan、colspan的table的实现方法
Feb 10 Javascript
jquery中使用$(#form).submit()重写提交表单无效原因分析及解决
Mar 25 Javascript
javascript之typeof、instanceof操作符使用探讨
May 19 Javascript
一个JavaScript的求爱小特效
May 09 Javascript
JavaScript中九种常用排序算法
Sep 02 Javascript
JavaScript如何获取数组最大值和最小值
Nov 18 Javascript
谈谈target=_new和_blank的不同之处
Oct 25 Javascript
javascript 利用arguments实现可变长参数
Nov 21 Javascript
JS中传递参数的几种不同方法比较
Jan 20 Javascript
认识jQuery的Promise的具体使用方法
Oct 10 jQuery
npm ci命令的基本使用方法
Sep 20 Javascript
vue backtop组件的实现完整代码
Apr 07 Vue.js
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
mysql 中InnoDB和MyISAM的区别分析小结
2008/04/15 PHP
Memcached常用命令以及使用说明详解
2013/06/27 PHP
php实现图片按比例截取的方法
2017/02/06 PHP
php7 错误处理机制修改实例分析
2020/05/25 PHP
自己整理的一个javascript日期处理函数
2010/10/16 Javascript
Jquery实现视频播放页面的关灯开灯效果
2013/05/27 Javascript
Javascript 浮点运算的问题分析与解决方法
2013/08/27 Javascript
js实现按一下删除键删除整个单词附demo
2014/09/05 Javascript
JavaScript设计模式之代理模式介绍
2014/12/28 Javascript
jQuery动画出现连续触发、滞后反复执行的解决方法
2015/01/28 Javascript
javascript实时获取鼠标坐标值并显示的方法
2015/04/30 Javascript
js实现带有介绍的Select列表菜单实例
2015/08/18 Javascript
JavaScript学习笔记整理_setTimeout的应用
2016/09/19 Javascript
JS验证 只能输入小数点,数字,负数的实现方法
2016/10/07 Javascript
jQuery 出现Cannot read property ‘msie’ of undefined错误的解决方法
2016/11/23 Javascript
JS常用加密编码与算法实例总结
2016/12/22 Javascript
Web制作验证码功能实例代码
2017/06/19 Javascript
js合并两个数组生成合并后的key:value数组
2018/05/09 Javascript
JS编写兼容IE6,7,8浏览器无缝自动轮播
2018/10/12 Javascript
js module大战
2019/04/19 Javascript
[01:09]DOTA2次级职业联赛 - 99战队宣传片
2014/12/01 DOTA
[56:57]LGD vs VP 2019DOTA2国际邀请赛淘汰赛 胜者组赛BO3 第一场 8.20.mp4
2019/08/22 DOTA
Python实现过滤单个Android程序日志脚本分享
2015/01/16 Python
pytorch 使用加载训练好的模型做inference
2020/02/20 Python
python代数式括号有效性检验示例代码
2020/10/04 Python
Python生成pdf目录书签的实例方法
2020/10/29 Python
Python爬取网站图片并保存的实现示例
2021/02/26 Python
调查研究项目计划书
2014/04/29 职场文书
后勤管理员岗位职责
2014/08/27 职场文书
债务纠纷委托书范本
2014/10/14 职场文书
考察邀请函范文
2015/01/31 职场文书
检察院起诉意见书
2015/05/20 职场文书
2015年宣传思想工作总结
2015/05/22 职场文书
MySQL触发器的使用
2021/05/24 MySQL
SpringBoot+Vue+JWT的前后端分离登录认证详细步骤
2021/09/25 Java/Android
python 多态 协议 鸭子类型详解
2021/11/27 Python