纯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弹出窗口插件 LeanModal的使用方法
Mar 10 Javascript
javascript异步编程的4种方法
Feb 19 Javascript
一个判断抢购时间是否到达的简单的js函数
Jun 23 Javascript
JS中使用sort结合localeCompare实现中文排序实例
Jul 23 Javascript
jquery实现个人中心导航菜单效果和美观都非常不错
Sep 02 Javascript
jQuery实现的经典竖向伸缩菜单效果代码
Sep 24 Javascript
jquery解析XML及获取XML节点名称的实现代码
May 18 Javascript
jQuery实现的可编辑表格完整实例
Jun 20 Javascript
纯jQuery实现前端分页功能
Mar 23 jQuery
vue 页面加载进度条组件实例
Feb 05 Javascript
vue内置指令详解
Apr 03 Javascript
vue+element UI实现树形表格带复选框的示例代码
Apr 16 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的FTP学习(二)[转自奥索]
2006/10/09 PHP
php 常用类汇总 推荐收藏
2010/05/13 PHP
PHP性能分析工具XHProf安装使用教程
2015/05/13 PHP
双冒号 ::在PHP中的使用情况
2015/11/05 PHP
PHP 数组基本操作方法详解
2016/06/17 PHP
PHP 输出缓冲控制(Output Control)详解
2016/08/25 PHP
PHP示例演示发送邮件给某个邮箱
2019/04/03 PHP
用Javascript同时提交多个Web表单的方法
2009/12/26 Javascript
浅谈JavaScript中的字符编码转换问题
2015/07/07 Javascript
轻松使用jQuery双向select控件Bootstrap Dual Listbox
2015/12/13 Javascript
javascript 操作cookies详解及实例
2017/02/22 Javascript
jQuery实现动态添加节点与遍历节点功能示例
2017/11/09 jQuery
Vue入门之数量加减运算操作示例
2018/12/11 Javascript
微信小程序 简易计算器实现代码实例
2019/09/02 Javascript
vue更改数组中的值实例代码详解
2020/02/07 Javascript
[34:56]Ti4冒泡赛LGD vs Liquid 1
2014/07/14 DOTA
详解Python中的Cookie模块使用
2015/07/06 Python
django模板加载静态文件的方法步骤
2019/03/01 Python
Python Django 实现简单注册功能过程详解
2019/07/29 Python
详解opencv中画圆circle函数和椭圆ellipse函数
2019/12/27 Python
Django数据模型中on_delete使用详解
2020/11/30 Python
python爬虫搭配起Bilibili唧唧的流程分析
2020/12/01 Python
伦敦剧院门票:From The Box Office
2018/06/30 全球购物
关于VPN
2012/06/10 面试题
电子商务个人自荐信
2013/12/12 职场文书
大学生实习感言
2014/01/16 职场文书
团日活动总结
2014/04/28 职场文书
青春励志演讲稿范文
2014/08/25 职场文书
2014年计生工作总结
2014/11/21 职场文书
幼儿园园长新年寄语2015
2014/12/08 职场文书
放弃遗产继承公证书
2015/01/26 职场文书
机修车间主任岗位职责
2015/04/08 职场文书
2015年宣传思想工作总结
2015/05/22 职场文书
信用卡收入证明范本
2015/06/12 职场文书
会议主持词结束语
2015/07/03 职场文书
详解MySQL中的主键与事务
2021/05/27 MySQL