原生JavaScript高性能批量倒计时

一 前言

因为倒计时这种JS效果几乎每个电商网站都会用到 , 所以这是每一个JS Boy必须要掌握的知识,那么本篇文章将讲解如何使用原生JS做出一个高性能批量倒计时的效果 , 那么既然要做倒计时效果,就必须使用到JavaScript中引用类型的知识之一:Date类型

二 Date类型

Date的由来

ECMAScript 中的Date 类型是在早期Java 中的java.util.Date 类基础上构建的。为此,Date类型使用自UTC(Coordinated Universal Time,国际协调时间)1970 年1 月1 日午夜(零时)开始经过的毫秒数来保存日期。在使用这种数据存储格式的条件下,Date 类型保存的日期能够精确到1970 年1月1 日之前或之后的285 616 年。

创建一个日期对象

?
1
2
3
4
5
/**在调用Date 构造函数而不传递参数的情况下,新创建的对象自动获得当前日期和时间。如果想根
 * 据特定的日期和时间创建日期对象,必须传入表示该日期的毫秒数(即从UTC 时间1970 年1 月1 日午
 * 夜起至该日期止经过的毫秒数)
 */
var now = new Date();
Date.parse( )

Date.parse( )方法接收一个表示日期的字符串参数,然后尝试根据这个字符串返回相应日期的毫秒数。ECMA-262 没有定义Date.parse( )应该支持哪种日期格式,因此这个方法的行为因实现而异,而且通常是因地区而异。将地区设置为米国的浏览器都接受下列格式:

1 月/日/年    例如:1/1/2018

2 英文月名 日,年    例如:January 1,2018

3 英文星期几 英文月名 日 年 时:分:秒 时区    例如:Tue May 25 2018 00:00:00 GTM-0700

4 ISO 8601 扩展格式 YYYY-MM-DDTHH:mm:ss:sssZ    例如:2018-01-01T00:00:00 (只有兼容ECMAScript 5的才支持这种格式

Example :

?
1
2
3
4
5
6
7
8
9
10
11
/**
 * 创建一个2018年1月1日的日期对象
 * 如果传入Date.parse()方法的字符串不能表示日期,那么它会返回NaN。
 */
var someDate = new Date(Date.parse('January 1, 2018'));
 
/**
 * 实际上,如果直接将表示日期的字符串传递给Date 构造函数,也会在后台调用Date.parse()。
 * 换句话说,下面的代码与前面的例子是等价的:
 */
var whatDate = new Date('January 1, 2018');
Date.UTC( )

Date.UTC( )方法同样也返回表示日期的毫秒数,但它与Date.parse( )在构建值时使用不同的信息。Date.UTC( )的参数分别是年份基于0 的月份(一月是0,二月是1,以此类推)月中的哪一天(1 到31)小时数(0 到23)分钟以及毫秒数。在这些参数中,只有前两个参数(年和月)是需的。如果没有提供月中的天数,则假设天数为1;如果省略其他参数,则统统假设为0。
Example :

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//GMT 时间 1996年 1 月 1 日午夜零时
var foo = new Date(Date.UTC(1996, 0));
 
//GMT 时间 2018年 2 月 5 日下午5:55:55
var bar = new Date(Date.UTC(2018, 1, 5, 17, 55, 55));
 
/**
 * 如同模仿Date.parse()一样,Date 构造函数也会模仿 Date.UTC(),但有一点明显不同:
 * 日期和时间都基于本地时区而非 GMT 来创建。不过,Date 构造函数接收的参数仍然与 Date.UTC()相同。
 * 因此,如果第一个参数是数值,Date 构造函数就会假设该值是日期中的年份,而第二个参数是月份,以此类推。
 * 据此,可以将前面的例子重写如下:
 */
//本地 时间 1996年 1 月 1 日午夜零时
var newFoo = new Date(1996, 0);
 
//本地 时间 2018年 2 月 5 日下午5:55:55
var newBar = new Date(2018, 1, 5, 17, 55, 55);
Date.now( )

ECMAScript 5 添加了Date.now( )方法,返回表示调用这个方法时的日期和时间的毫秒数。此方法简化了使用Date对象分析代码的工作。
Example :

?
1
2
3
4
5
6
7
8
9
10
//取得开始时间
var start = Date.now();
 
//调用函数
doSomething();
 
//取得停止时间
var stop = Date.now();
var result = stop - start;
console.log('doSomething方法 运行时间为 :' + result + '毫秒');
valueOf( )

Date 类型的valueOf( )方法,不会返回字符串,而是返回日期的毫秒表示。因此,可以方便使用比较操作符来比较日期值。

Example :

?
1
2
3
4
5
6
7
/**
 * 当2个对象进行比较时,JS引擎会隐式调用对象的valueOf()方法进行比较,所以会输出一下结果
 */
var date1 = new Date(2018, 0);
var date2 = new Date(2018, 1);
console.log(date1 > date2);    //output: false;
console.log(date1 < date2);    //output: true;
三 利用Date对象制作批量倒计时效果

HTML代码:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>CountDown - Demo</title>
    </head>
    <body>
        <section>
            <!-- 倒计时DIV -->
            <div class="countdown" data-time="2018/01/15 11:20:40">
                <div>
                    <img src="./logo.jpg">
                </div>
                <div class="time">
                    <b class="hour1">0</b><b class="hour2">0</b>
                    <b>:</b>
                    <b class="min1">0</b><b class="min2">0</b>
                    <b>:</b>
                    <b class="sec1">0</b><b class="sec2">0</b>
                </div>
            </div>
            <!-- 倒计时DIV -->
            <div class="countdown" data-time="2018/01/15 00:20:13">
                <div>
                    <img src="./logo.jpg">
                </div>
                <div class="time">
                    <b class="hour1">0</b><b class="hour2">0</b>
                    <b>:</b>
                    <b class="min1">0</b><b class="min2">0</b>
                    <b>:</b>
                    <b class="sec1">0</b><b class="sec2">0</b>
                </div>
            </div>
            <!-- 倒计时DIV -->
            <div class="countdown" data-time="2018/01/15 16:50:22">
                <div>
                    <img src="./logo.jpg">
                </div>
                <div class="time">
                    <b class="hour1">0</b><b class="hour2">0</b>
                    <b>:</b>
                    <b class="min1">0</b><b class="min2">0</b>
                    <b>:</b>
                    <b class="sec1">0</b><b class="sec2">0</b>
                </div>
            </div>
        </section>
    </body>
</html>
JavaScript代码:
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
<script>
    function C(d){ return document.getElementsByClassName(d); }
    //初始化各种参数
    var timers = {}, ht = null, ht2 = null, mt = null, mt2 = null,
        st = null, st2 = null, lists = null, l = null;
    //核心函数setTime 实现倒计时效果
    function setTime(i){
        var f = lists[i].getAttribute('data-time');
        if(f){
            //此处为了兼容2种时间格式 safari需要的格式为UTC格式:2018,0,1,00,00,00
            var future = new Date(f);
            if(!(future.getFullYear() > 0)){
                var arr = f.split(/[- : \/]/);
                future = new Date(arr[0], arr[1] - 1, arr[2], arr[3], arr[4], arr[5]);
            }
        }
        var cha = future.getTime() - new Date().getTime();
        if(cha < 0){
            ht[i].innerHTML = 0;
            ht2[i].innerHTML = 0;
            mt[i].innerHTML = 0;
            mt2[i].innerHTML = 0;
            st[i].innerHTML = 0;
            st2[i].innerHTML = 0;
            return;
        }
        var hour = parseInt(cha / 3600000);
        var hour1 = parseInt(hour / 10);
        var hour2 = hour % 10;
        cha = cha % 3600000;
        var min = parseInt(cha / 60000);
        var min1 = parseInt(min / 10);
        var min2 = min % 10;
        cha = cha % 60000;
        var sec = parseInt(cha / 1000);
        var sec1 = parseInt(sec / 10);
        var sec2 = sec % 10;
        ht[i].innerHTML = hour1;
        ht2[i].innerHTML = hour2;
        mt[i].innerHTML = min1;
        mt2[i].innerHTML = min2;
        st[i].innerHTML = sec1;
        st2[i].innerHTML = sec2;
    }
    //调用Run开启倒计时 若中途页面使用AJAX局部刷新DOM时 重新调用一次该方法即可
    function Run(){
        ht = C('hour1'); ht2 = C('hour2');
        mt = C('min1'); mt2 = C('min2');
        st = C('sec1'); st2 = C('sec2');
        lists = C('countdown'); l = lists.length;
        if(l > 0 && ht.length > 0){
            var i = 0;
            for(;i < l;i++){
                //使用匿名函数保存变量i
                (function(i){
                    setTime(i);
                    //清除定时器 避免ajax刷新DOM
                    if(timers['timer' + i]){ clearInterval(timers['timer' + i]); }
                    //setInterval(timeChg(i),1000)这种写法不能够传参 所以需要使用匿名函数形式
                    timers['timer' + i] = setInterval(function(){
                        setTime(i);
                    }, 1000);
                })(i);
            }
        }
    }
    Run();
</script>
本项目gayhub传送门

发布评论
还没有评论,快来抢沙发吧!