纯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 相关文章推荐
Z-Blog中用到的js代码
Mar 15 Javascript
疯掉了,尽然有js写的操作系统
Apr 23 Javascript
深入理解JavaScript中的对象
Jun 04 Javascript
JavaScript希尔排序、快速排序、归并排序算法
May 08 Javascript
Javascript打印局部页面实例
Jun 21 Javascript
EsLint入门学习教程
Feb 17 Javascript
JS实现中国公民身份证号码有效性验证
Feb 20 Javascript
Bootstrap Table使用整理(五)之分页组合查询
Jun 09 Javascript
在HTML文档中嵌入JavaScript的四种方法
May 07 Javascript
vue之将echart封装为组件
Jun 02 Javascript
解决vue单页面应用中动态修改title问题
Jun 09 Javascript
layui 数据表格+分页+搜索+checkbox+缓存选中项数据的方法
Sep 21 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函数解决SQL injection
2006/12/09 PHP
PHP将身份证正反面两张照片合成一张图片的代码
2017/04/08 PHP
php如何比较两个浮点数是否相等详解
2019/02/12 PHP
javaScript 动态访问JSon元素示例代码
2013/08/30 Javascript
js实现iframe跨页面调用函数的方法
2014/12/13 Javascript
javascript算法题:求任意一个1-9位不重复的N位数在该组合中的大小排列序号
2015/04/01 Javascript
jquery解析json格式数据的方法(对象、字符串)
2015/11/24 Javascript
JavaScript对象参数的引用传递
2016/01/14 Javascript
纯js实现瀑布流布局及ajax动态新增数据
2016/04/07 Javascript
教你一步步用jQyery实现轮播器
2016/12/18 Javascript
100行代码理解和分析vue2.0响应式架构
2017/03/09 Javascript
vue.js开发环境安装教程
2017/03/17 Javascript
Vue 框架之动态绑定 css 样式实例分析
2018/11/14 Javascript
使用vue完成微信公众号网页小记(推荐)
2019/04/28 Javascript
富文本编辑器vue2-editor实现全屏功能
2019/05/26 Javascript
JavaScript React如何修改默认端口号方法详解
2020/07/28 Javascript
测试、预发布后用python检测网页是否有日常链接
2014/06/03 Python
Python中MYSQLdb出现乱码的解决方法
2014/10/11 Python
简单的抓取淘宝图片的Python爬虫
2014/12/25 Python
尝试用最短的Python代码来实现服务器和代理服务器
2016/06/23 Python
Python基础之函数的定义与使用示例
2019/03/23 Python
Python字符串格式化f-string多种功能实现
2020/05/07 Python
Python捕获异常堆栈信息的几种方法(小结)
2020/05/18 Python
完美解决pycharm 不显示代码提示问题
2020/06/02 Python
纯DOM+CSS3实现简单的小风车动画
2016/09/27 HTML / CSS
HTML5对手机页面长按会粘贴复制禁用的解决方法
2016/07/19 HTML / CSS
Woolworth官网:澳洲第一大超市
2017/06/25 全球购物
波兰最早的运动鞋精品店之一:Street Supply
2019/08/29 全球购物
中专药剂专业应届毕的自我评价
2013/12/27 职场文书
公司薪酬管理制度
2014/01/31 职场文书
英语教学随笔感言
2014/02/20 职场文书
公司联欢晚会主持词
2014/03/22 职场文书
2014公司党员自我评价范文
2014/09/11 职场文书
财务会计求职信范文
2015/03/20 职场文书
戒赌保证书
2015/05/11 职场文书
vue中三级导航的菜单权限控制
2021/03/31 Vue.js