纯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 相关文章推荐
如何判断图片地址是否失效
Feb 02 Javascript
深入理解JavaScript系列(14) 作用域链介绍(Scope Chain)
Apr 12 Javascript
JavaScript中json对象和string对象之间相互转化
Dec 26 Javascript
jquery ztree实现下拉树形框使用到了json数据
May 14 Javascript
jQuery插件Elastislide实现响应式的焦点图无缝滚动切换特效
Apr 12 Javascript
轻量级网页遮罩层jQuery插件用法实例
Jul 31 Javascript
快速使用Bootstrap搭建传送带
May 06 Javascript
JS打印组合功能
Aug 04 Javascript
详解AngularJS中的表单验证(推荐)
Nov 17 Javascript
JS+canvas实现的五子棋游戏【人机大战版】
Jul 19 Javascript
基于Vue2x实现响应式自适应轮播组件插件VueSliderShow功能
May 16 Javascript
vue通过style或者class改变样式的实例代码
Oct 30 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 文件上传进度条的两种实现方法的代码
2007/11/25 PHP
PHP中文件缓存转内存缓存的方法
2011/12/06 PHP
php实现的Timer页面运行时间监测类
2014/09/24 PHP
PHP版本常用的排序算法汇总
2015/12/20 PHP
Smarty分页实现方法完整实例
2016/05/11 PHP
详解PHP归并排序的实现
2016/10/18 PHP
php自定义截取中文字符串-utf8版
2017/02/27 PHP
php实现的redis缓存类定义与使用方法示例
2017/08/09 PHP
PHP工厂模式简单实现方法示例
2018/05/23 PHP
jQuery实现类似滑动门切换效果的层切换
2013/09/23 Javascript
js的参数有长度限制吗?发现不能超过2083个字符
2014/04/20 Javascript
JavaScript数值数组排序示例分享
2014/05/27 Javascript
javascript搜索框点击文字消失失焦时文本出现
2014/09/18 Javascript
jQuery使用正则表达式限制文本框只能输入数字
2016/06/18 Javascript
微信小程序实现图片自适应(支持多图)
2017/01/25 Javascript
详解windows下vue-cli及webpack 构建网站(三)使用组件
2017/06/17 Javascript
[js高手之路]寄生组合式继承的优势详解
2017/08/28 Javascript
浅谈js基础数据类型和引用类型,深浅拷贝问题,以及内存分配问题
2017/09/02 Javascript
利用CDN加速react webpack打包后的文件详解
2018/02/22 Javascript
浅谈js闭包理解
2019/03/28 Javascript
[00:57]深扒TI7聊天轮盘语音出处5
2017/05/11 DOTA
python使用xlrd与xlwt对excel的读写和格式设定
2017/01/21 Python
python绘制铅球的运行轨迹代码分享
2017/11/14 Python
使用python画个小猪佩奇的示例代码
2018/06/06 Python
Python从列表推导到zip()函数的5种技巧总结
2019/10/23 Python
在Python中使用filter去除列表中值为假及空字符串的例子
2019/11/18 Python
tensorflow 查看梯度方式
2020/02/04 Python
Pycharm连接gitlab实现过程图解
2020/09/01 Python
python实现视频压缩功能
2020/12/18 Python
Python实现一个论文下载器的过程
2021/01/18 Python
英国办公用品商店:Office Outlet
2018/04/04 全球购物
戴森香港官方网站:Dyson香港
2021/02/11 全球购物
JMS中Topic和Queue有什么区别
2013/05/15 面试题
《九寨沟》教学反思
2014/04/08 职场文书
临床医学生职业规划书范文
2014/10/25 职场文书
乡镇司法所2015年度工作总结
2015/10/14 职场文书