纯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 BS,dialog控件自适应大小
Jul 06 Javascript
从零开始学习jQuery (三) 管理jQuery包装集
Feb 23 Javascript
javascript去掉前后空格的实例
Nov 07 Javascript
jQuery层级选择器用法分析
Feb 10 Javascript
使用jQuery给input标签设置默认值
Jun 20 Javascript
jQuery增加、删除及修改select option的方法
Aug 19 Javascript
Bootstrap基本样式学习笔记之表格(2)
Dec 07 Javascript
详解本地Node.js服务器作为api服务器的解决办法
Feb 28 Javascript
Bootstrap Table从零开始
Jun 30 Javascript
Angular CLI 安装和使用教程
Sep 13 Javascript
Vue.js划分组件的方法
Oct 29 Javascript
nestjs中异常过滤器Exceptionfilter的具体使用
Feb 07 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
成本8450万,票房仅2亿,口碑两极分化,又一部DC电影扑街了
2020/04/09 欧美动漫
PHP setcookie() cannot modify header information 的解决方法
2009/01/09 PHP
Laravel框架路由配置总结、设置技巧大全
2014/09/03 PHP
Codeigniter的一些优秀特性总结
2015/01/21 PHP
Avengerls vs Newbee BO3 第一场2.18
2021/03/10 DOTA
javascript 冒号 使用说明
2009/06/06 Javascript
javascript中RegExp保留小数点后几位数的方法分享
2013/08/13 Javascript
扩展IE中一些不兼容的方法如contains、startWith等等
2014/01/09 Javascript
Javascript中arguments对象详解
2014/10/22 Javascript
Node.js中HTTP模块与事件模块详解
2014/11/14 Javascript
详谈jQuery操纵DOM元素属性 attr()和removeAtrr()方法
2015/01/22 Javascript
nodejs 搭建简易服务器的图文教程(推荐)
2017/07/18 NodeJs
深入浅析JavaScript中的RegExp对象
2017/09/18 Javascript
vue视图不更新情况详解
2019/05/16 Javascript
layui时间控件选择时间范围的实现方法
2019/09/28 Javascript
一个基于flask的web应用诞生 使用模板引擎和表单插件(2)
2017/04/11 Python
python中for循环输出列表索引与对应的值方法
2018/11/07 Python
python 两个数据库postgresql对比
2019/10/21 Python
python 安装impala包步骤
2020/03/28 Python
CSS3制作翻转效果_动力节点Java学院整理
2017/07/11 HTML / CSS
英国巧克力贸易公司:Chocolate Trading Company
2017/03/21 全球购物
旷课检讨书3000字
2014/02/04 职场文书
学习十八届三中全会精神实施方案
2014/02/17 职场文书
讲文明树新风公益广告宣传方案
2014/02/25 职场文书
《蜗牛的奖杯》教后反思
2014/04/24 职场文书
企业承诺书怎么写
2014/05/24 职场文书
中专生自荐信
2014/06/25 职场文书
大学拉赞助协议书范文
2014/09/26 职场文书
2014年电工工作总结
2014/11/20 职场文书
2014年工程部工作总结
2014/11/25 职场文书
2015年光棍节活动总结
2015/03/24 职场文书
2015年事业单位工作总结
2015/04/27 职场文书
婚礼嘉宾致辞
2015/07/28 职场文书
物业保洁员管理制度
2015/08/05 职场文书
2016中秋节晚会开场白
2015/11/26 职场文书
 python中的元类metaclass详情
2022/05/30 Python