原生JS实现简单计时器

Chanx 699 字 3 分钟阅读

在线预览: 点我查看demo

做什么

用原生的js实现一个简单计时器。比如说记录编辑框他输入内容所用的时间。

怎么做

HTML

一个编辑框和一个时间显示器

JS

编辑框获得焦点时setInterval()进行计时,失去焦点时clearInterval()取消计时 另外利用localStorage可以进行数据的保存,刷新后能读取上次的时间

代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>计时器</title>
</head>
<body>
    <div id="container">
        <h3 id="status">计时器案例 - 未做题</h3>
        <textarea rows="5" cols="20" onfocus="inputFocus()" onblur="innputBlur()" placeholder="点击输入框开始计时"></textarea>
        <h4 id="timer">做题时长: 0时0分0秒</h4>
        <button onclick="resetTime()">重新计时</button>
    </div>
 
    <script>
        var second = 0; //记录时间-秒
        var timing;     //定时器
 
        //更新显示时间
        function updateTime(){
            let _hour = Math.floor(second /3600);
            let _minute =  Math.floor((second%3600) / 60);
            let _second = (second%3600) %60;
            document.getElementById("timer").innerText = "做题时长:"+_hour+"时"+_minute+"分"+_second+"秒";
        }
 
        function resetTime(){
            window.localStorage.setItem("status",0);
            second = 0;
            updateTime();
        }
        //输入框获得焦点时开始计时
        function inputFocus(){
            document.getElementById("status").innerText = "计时器案例 - 做题中";
            timing = setInterval(function(){
                second ++;
                updateTime();
            },1000);
        }
 
        //输入框失去焦点取消计时
        function innputBlur(){
            document.getElementById("status").innerText = "计时器案例 - 未做题";
            clearInterval(timing);
        }
 
        //网页加载完执行数据初始化
        window.onload = function(){
            let t = window.localStorage.getItem("time");
            second = t?t:0; //无数据时默认为0
            updateTime();
        }
 
        //网页刷新前进行数据缓存
        window.onbeforeunload = function(){
            innputBlur();
            window.localStorage.setItem("time",second);
        }
    </script>
</body>
</html>

思考

是否可以利用两个开始和结束的两个时间戳获取一个时间段?但是需要注意的是我们new Date()获取的时间可能会受到系统时间的影响,导致获取的数据不合法。(2020-06-06)

setTimeoutsetInterval究竟谁更适合实现计时?

看了红宝书,里面说了一句setInterval很少会出现在生产环境。于是想到了该计时器的实现。

setInterval到了时间就会把回调函数推进消息队列,所以不适合长时间和阻塞的循环任务,比如时间长的ajax不断被推进消息队列,然后消息队列越来越长,影响整个系统。与此同时,不能保证两次任务之间保持间隔。setTimeout实现循环任务就能保证任务有间隔,上一次任务成功回调才到下一次。

然而对于计时器这种比较简单的任务来说,不至于出现setInterval被塞爆的情况。而且计时器我们关注的是到时间就把回调推进消息队列,而不是两次时间增长之间保持间隔。

所以我认为在这个场景下,setInterval是更适合计时器的。(2020-11-18)

另外,由于JS的运行机制。两种定时器的实现方式都是有微小误差的。而performance中的计时api适合于性能检测等高精度时间计算,不适合用在这

按下 K 进行搜索