使用JavaScript编写的时钟计时器中,clearInterval()无法正常工作

5
我是一名JavaScript和编程新手。我目前在处理一些代码时遇到了问题,想知道是否有人能给我一些建议。
背景:
我正在处理的代码非常简单;有一个时钟,当前时间通过setInterval更新一秒钟。
在时钟下方有一个按钮,上面写着“停止”,按下后,它将清除Interval,按钮将显示“开始”。如果再次按下标有“开始”的按钮,则会继续计时器以当前时间运行。因此,这个按钮可以切换时钟的间隔,并根据其状态更改为“开始”或“停止”。 W3Schools: JS Timing是我最初参考的网站,用于创建我正在使用的代码。这是我学习setInterval和clearInterval工作原理的地方。我还采用了一些示例代码并进行了调整,以尝试使时钟计时器切换开关。
代码:

var clock09 = window.setInterval(myTimer09, 1000);

function myTimer09() {
  var d = new Date();
  var t = d.toLocaleTimeString();
  document.getElementById("req09").innerHTML =
    "<h1>" + t + "</h1>";
}

function toggle10() {
  var button = document.getElementById("button10").innerHTML;
  if (button == "Stop") {
    window.clearInterval(clock09);
    document.getElementById("button10").innerHTML = "Start";
  } else {
    clock09 = window.setInterval(myTimer09, 1000);

    document.getElementById("button10").innerHTML = "Stop";
  }
}
<span class="center" id="req09"></span>
<button type="button" id="button10" onclick="toggle10()" class="button">Stop</button>

https://jsfiddle.net/dtc84d78/

问题:

我的问题是,按钮从“停止”按钮切换到“开始”按钮,但 clearInterval 未应用于setInterval的变量。

我已在SO中搜索了类似的问题,例如这个, 并按照他们的建议去尝试,但还是没有解决。经过数小时的尝试后,我决定直接从W3Schools复制并粘贴一些示例到jsFiddle中,但这甚至也不起作用(包含在jsfiddle链接中)?

我真的很想知道为什么任何与 clearInterval()相关的东西对我都不起作用?这可能是我的电脑,浏览器或其他任何原因吗?我来到SO作为我的最后资源,所以如果有人能给我一些解决这个问题的指导,我会以你的名字命名我的第一个孩子。

提前感谢您。

额外信息:

我目前正在使用Mac桌面,使用Komodo编写代码,使用Google Chrome预览代码。

更新:

我在评论中提到过,代码是在外部的 .js 文件中编写的。然后将该文件链接在 head 标签之间,并在 body 结束标签之前链接。

<head>
  <meta charset="utf-8" />
  <title>Program</title>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="stylesheet" href="css/normalize.css">
  <link rel="stylesheet" href="css/program-05.css">
  <script type="text/javascript" src="scripts/program-05.js">
    /* <![CDATA[ */
    /* ]]> */
  </script>
</head>

<body onload="checkCookies(); setTimeout(function() { func11() }, 5000);">

  . . . code for stuff

  . . . code for clock timer

  . . . code for other stuff

  <script type="text/javascript" src="scripts/program-05.js">
    /* <![CDATA[ */
    /* ]]> */
  </script>
</body>

在@Matz提到将时钟定时器js代码放在头部后,代码运行良好!目前在头部的样子如下。

<head>
  <meta charset="utf-8" />
  <title>Program</title>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="stylesheet" href="css/normalize.css">
  <link rel="stylesheet" href="css/program-05.css">
  <script type="text/javascript" src="scripts/program-05.js">
    /* <![CDATA[ */
    /* ]]> */
  </script>
  <script>
    ///*
    var clock09 = window.setInterval(myTimer09, 1000);

    function myTimer09() {
      var d = new Date();
      var t = d.toLocaleTimeString();
      document.getElementById("req09").innerHTML =
        "<h1>" + t + "</h1>";
    }

    function toggle10() {
        var button = document.getElementById("button10").innerHTML;
        if (button == "Stop") {
          window.clearInterval(clock09);
          document.getElementById("button10").innerHTML = "Start";
        } else {
          clock09 = window.setInterval(myTimer09, 1000);

          document.getElementById("button10").innerHTML = "Stop";
        }
      }
      //*/
  </script>
</head>

尽管这很有效,但我现在想弄清楚为什么时钟定时器js代码在直接放在head部分时能够正常工作,而与将其保留在外部.js文件中(并将外部文件链接到文档中)相比呢?我该怎么做才能使它在外部文件中正常工作?

你可以通过将 function toggle10() { 更改为 document.toggle10 = function() { 来简单修复你的代码。 - Matt Way
我刚意识到代码在SO代码片段中运行!不幸的是,我正在处理的代码需要在一个index.html文件中,而我在这个文件中使用这个代码时并没有得到我想要的结果。我目前正在尝试看看是否有任何给出的建议可以解决这个问题。注意:所有的JavaScript都在一个外部的.js文件中,它链接在HEAD和BODY标签之前。我也没有控制台错误。 - unavailableUsername
到目前为止,在所有建议中,将此问题的JavaScript代码放在头标签之间对我有效!现在我的外部.js文件已链接,其后是时钟计时器的js代码。 - unavailableUsername
看起来这篇文章越来越长了,而且你的最初问题,即JS没有被内联调用的问题已经解决了,是吗?至于外部JS文件的问题,那就是另一个问题了,建议单独发布。 - Shashank Agrawal
我想我会直接在HTML文件中发布。在发布其他内容之前,我会再搜索一下有关外部JS文件问题的信息。谢谢大家提供的所有建议! - unavailableUsername
4个回答

2

问题:

这是因为默认的加载类型设置为onLoad,它将您的javascript代码包装在window.onload = function() {}中,因此您的函数范围被限制在onload函数中,并且在外部不可用:

enter image description here

解决方案:

点击Fiddle的Javascript部分中的Javascript设置,将其更改为No wrap - in body,它将工作,因为这将把您的Javascript代码放置在body标记中。

附加说明:

您的代码也可以通过StackOverflow片段正常工作:

/*My Problem*/
var clock09 = window.setInterval(myTimer09, 1000);

function myTimer09() {
  var d = new Date();
  var t = d.toLocaleTimeString();
  document.getElementById("req09").innerHTML =
    "<h1>" + t + "</h1>";
}

function toggle10() {
  var button = document.getElementById("button10").innerHTML;
  if (button == "Stop") {
    window.clearInterval(clock09);
    document.getElementById("button10").innerHTML = "Start";
  } else {
    clock09 = window.setInterval(myTimer09, 1000);

    document.getElementById("button10").innerHTML = "Stop";
  }
}

/*W3S Problem*/
var myVar = setInterval(myTimer, 1000);

function myTimer() {
  var d = new Date();
  document.getElementById("demo").innerHTML =
    d.toLocaleTimeString();
}
<!-- My Problem -->
<span class="center" id="req09"></span>
<button type="button" id="button10" onclick="toggle10()" class="button">Stop</button>

<hr>
<hr>
<!-- W3S Problem -->
<p id="demo"></p>
<button onclick="clearInterval(myVar)">Stop time</button>

建议

关注点分离

我建议您将 JavaScript 代码移到外部文件中,然后使用 script 标签将其包含在 HTML 中。例如,您将代码移动到 app.js 中,然后在 HTML 中包含它:

<!-- make sure the path here is relative to the current HTML -->
<script src="./app.js"></script>

1
很高兴你和@spen提出了这个问题,因为现在我知道为什么它在fiddle上没有工作了。我的尝试是将脚本粘贴在head标签之间进行复制。有没有关于如何使用外部.js文件中的代码使代码工作的建议?最坏的情况下,我会把脚本留在head标签之间。顺便说一句,我真的很喜欢图形的使用!让我更容易跟随。 - unavailableUsername
进入时,所有的js代码都在外部文件中。该文件链接到html文档的head标签之间,以及结束body标签之前。它看起来像这样:<script type="text/javascript" src="scripts/program-05.js">/* <![CDATA[ */ /* ]]> */</script>。不幸的是,这种方法不起作用。目前外部文件已经链接,因为我有其他东西在那里,但计时器时钟的js代码在外部文件后的head部分的script标签之间。 - unavailableUsername
你能提供一个 Fiddle 来重现这个问题吗? - Shashank Agrawal
我已经编辑了我的帖子,因为我无法在jsfiddle中包含我的头部部分的外观和当前外观。 - unavailableUsername

0
在 myTimer09 函数中,您正在声明一个新的日期变量,因此每次调用它时都会显示当前时间。您应该在函数外部声明时间,然后将其传递给函数。当您停止计时器时,应保存时间值,以便您可以使用该值重新启动。

尝试过了,但它只显示了当前时间,并没有更新每秒的时间间隔。而且我需要的是当按下“开始”按钮时,时钟计时器将继续运行,但使用当前时间,而不是停止时的值。所以我认为这不会起作用。感谢您的建议! - unavailableUsername

0

这似乎是JSFiddle的问题。

onclick处理程序正在寻找未定义的window.toggle10(请检查控制台中的错误)。 看起来这是{{link1:其他人在JSFiddle上遇到的问题}}

我已经将您的代码复制并粘贴到JSbin中,它按照描述工作!


现在我明白为什么 JS 在 Fiddle 中无法工作了。我尝试复制它,将脚本粘贴在 head 标签之间。有没有关于如何使用外部 .js 文件使代码工作的建议?最坏的情况是我会把脚本留在 head 标签之间。 - unavailableUsername

0
一种解决计时器启动和停止的方法是将JavaScript代码移动到HEAD标签之间,这样函数在HTML加载时就已经声明了。我已经让它起作用了:
<html>
  <head>
    <title>Stuff</title>

    <script >

      var clock09 = window.setInterval(myTimer09, 1000);

      .... your code

   </script>

  </head>
  <body>
    <span class="center" id="req09"></span>
    <button type="button" id="button10" onclick="toggle10()" class="button">Stop</button>

  </body>
</html>

我按照Matz的建议将js代码放在head标签之间。结果:它真的起作用了!我很高兴这个方法有效,但我需要找到一个不需要将其包含在head标签中、可以保留在外部文件中的解决方案。最坏的情况下,我会选择这种方式。有什么建议吗? - unavailableUsername
只需将JavaScript放入文件中,例如timerstuff.js,并将脚本标记更改为:<script src ='timerstuff.js'> </ script>。 它仍然位于head标签中,但代码在单独的文件中。 - Matz

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