按下启动按钮如何使时钟滴答作响

3

如何通过按下开始按钮使时钟滴答作响。如果我多次按“开始”按钮,时间将被更新,但我只需要每秒按一次即可更新时钟。目前不清楚为什么递归函数调用无法正常工作。

<!DOCTYPE HTML>
<html>

<body>


  <input type="button" onclick="clock.clockStart()" value="Start">

  <input type="button" onclick="clock.clockStop()" value="Stop">

  <div class='clocks'>
    <span class='hours'></span>
    <span class='minutes'></span>
    <span class='seconds'></span>
  </div>
  <script>
    'use strict';

    class Clock {
      constructor() {
        this.hh = document.querySelector('.hours');
        this.mm = document.querySelector('.minutes');
        this.ss = document.querySelector('.seconds');
      }


      clockStart() {
        let self = this;

        self.date = new Date();

        self.timer = setTimeout(function tick1() {

          self.hh.textContent = '' + self.date.getHours();
          self.mm.textContent = ': ' + self.date.getMinutes();
          self.ss.textContent = ': ' + self.date.getSeconds();

          self.timer = setTimeout(tick1, 1000);
        }, 1000);
      }
      clockStop() {
        clearTimeout(this.timer);
      }

    }

    let clock = new Clock();
  </script>
</body>

</html>

感谢您的信任。

日期始终不变..... - epascarello
2个回答

4

在你的代码中,你设置了self.date = new Date();,那是那一时刻的时间戳。它不会持续更新。

因此,如果你想要时间改变,你需要将其放在定时器内,并在每次迭代中声明它。

self.timer = setTimeout(function tick1() {
    self.date = new Date();
    /* rest of your code */

1

我对内容进行了一些修改,并添加了注释以解释我做出这些修改的原因。希望这样能更清晰明了。

<!DOCTYPE HTML>
<html>

<body>


  <input type="button" onclick="clock.clockStart()" value="Start">

  <input type="button" onclick="clock.clockStop()" value="Stop">

  <div class='clocks'>
    <span class='hours'></span>
    <span class='minutes'></span>
    <span class='seconds'></span>
  </div>
  <script>
    'use strict';

    class Clock {
      constructor() {
        this.hh = document.querySelector('.hours');
        this.mm = document.querySelector('.minutes');
        this.ss = document.querySelector('.seconds');
      }


      clockStart() {
        // There is no need for self. You're using ES6 and thus you have fat 
        // arrow methods that keep the this reference the same.

        // Use setInterval instead of useTimeout, you want this to be called 
        // every second. In addition, using a fat arrow function will make sure 
        // this still refers your instance of the Clock class.
        this.timer = setInterval(() => {
          // You need to refresh date each time before showing it in your UI.
          this.date = new Date();
          this.hh.textContent = '' + this.date.getHours();
          this.mm.textContent = ': ' + this.date.getMinutes();
          this.ss.textContent = ': ' + this.date.getSeconds();

        }, 1000);
      }
      clockStop() {
        // When stop is clicked, cancel the interval.
        clearInterval(this.timer);
      }

    }

    let clock = new Clock();
  </script>
</body>

</html>


递归setTimeout是一种比setInterval更灵活的定时方法,因为下一次执行的时间可以根据当前执行的结果以不同的方式进行调度。谢谢。 - Aliaksandr Pitkevich
例如,我们有一个服务,每5秒轮询服务器以获取新数据。如果服务器负载过高,您可以将轮询间隔增加到10、20、60秒等,并在一切恢复正常后返回原来的间隔。如果我们定期传递负载处理器的任务,则可以估计执行它们所需的时间,并计划更早或更晚地启动下一个任务。递归setTimeout保证调用之间的暂停,setInterval则不保证。 - Aliaksandr Pitkevich
当然,这是正确的。但你正在询问每秒更新计时器的问题,没有提到滑动间隔。在这种情况下,使用 setInterval 每秒显示不同的时间,更清晰地传达了代码的意图。 - Thijs

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接