纯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 相关文章推荐
Extjs学习笔记之五 一个小细节renderTo和applyTo的区别
Jan 07 Javascript
改写一个简单的菜单 弹性大小
Dec 02 Javascript
js实现匹配时换色的输入提示特效代码
Aug 17 Javascript
JavaScript实现的多个图片广告交替显示效果代码
Sep 04 Javascript
js实现获取div坐标的方法
Nov 16 Javascript
JavaScript学习总结之JS、AJAX应用
Jan 29 Javascript
整理一下常见的IE错误
Nov 18 Javascript
Vue渲染函数详解
Sep 15 Javascript
react-native封装插件swiper的使用方法
Mar 20 Javascript
Vue 项目分环境打包的方法示例
Aug 03 Javascript
Node 搭建一个静态资源服务器的实现
May 20 Javascript
基于vue与element实现创建试卷相关功能(实例代码)
Dec 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
UTF8编码内的繁简转换的PHP类
2009/07/09 PHP
PHP中防止SQL注入攻击和XSS攻击的两个简单方法
2010/04/15 PHP
抓取并下载CSS中所有图片文件的php代码
2011/09/26 PHP
mac下Apache + MySql + PHP搭建网站开发环境
2014/06/02 PHP
php中多维数组按指定value排序的实现代码
2014/08/19 PHP
PHP结合Ueditor并修改图片上传路径
2016/10/16 PHP
PHP正则表达式匹配替换与分割功能实例浅析
2017/02/04 PHP
JavaScript Base64编码和解码,实现URL参数传递。
2006/09/18 Javascript
基于jQuery的表格操作插件
2010/04/22 Javascript
jQuery中json对象的复制方式介绍(数组及对象)
2013/06/08 Javascript
JavaScript定时器详解及实例
2013/08/01 Javascript
jquery层级选择器(匹配父元素下的子元素实现代码)
2016/09/05 Javascript
javascript实现图片左右滚动效果【可自动滚动,有左右按钮】
2016/09/19 Javascript
vue对storejs获取的数据进行处理时遇到的几种问题小结
2018/03/20 Javascript
ng-alain表单使用方式详解
2018/07/10 Javascript
vue自定义指令的创建和使用方法实例分析
2018/12/04 Javascript
Python 代码性能优化技巧分享
2012/08/07 Python
详细解析Python中的变量的数据类型
2015/05/13 Python
Python如何快速上手? 快速掌握一门新语言的方法
2017/11/14 Python
Python遍历pandas数据方法总结
2018/02/09 Python
python实现教务管理系统
2018/03/12 Python
python使用 __init__初始化操作简单示例
2019/09/26 Python
python wxpython 实现界面跳转功能
2019/12/17 Python
解决django框架model中外键不落实到数据库问题
2020/05/20 Python
CSS3绘制六边形的简单实现
2016/08/25 HTML / CSS
AmazeUI 输入框组的示例代码
2020/08/14 HTML / CSS
公务员个人自我评价分享
2013/11/06 职场文书
如何写一份好的自荐信
2014/01/02 职场文书
自行车租赁公司创业计划书
2014/01/28 职场文书
适用于所有创业者的创业计划书
2014/02/05 职场文书
机械专业技术员求职信
2014/06/14 职场文书
课程设计的心得体会
2014/09/03 职场文书
学校食堂标语
2014/10/06 职场文书
教师党的群众路线教育实践活动个人整改方案
2014/10/31 职场文书
2016年党课培训学习心得体会
2016/01/07 职场文书
《艾尔登法环》1.03.3补丁上线 碎星伤害调整
2022/04/07 其他游戏