在 CodePen 上使用 Vue.js 构建番茄钟计时器

2025-06-07

在 CodePen 上使用 Vue.js 构建番茄钟计时器

我关注Scotch.io上的挑战项目有一段时间了,看到一个我特别想尝试做的项目。它是Scotch.io 挑战 #6的番茄钟。我一直想测试一下自己的技能,所以想试试这个。

设置

设置很简单,因为已经有了Codepen(如下),里面已经完成了所有必要的 HTML 和 CSS 工作。主要工作已经完成,是时候开始着手这项挑战的 JavaScript 部分了。

这个 Codepen 无法使用

第一步

我要做的第一件事是使用我需要的所有变量来设置我的数据。

data: {
    message: 'Let the countdown begin!!',
    timerRunning: false
}
Enter fullscreen mode Exit fullscreen mode

这仅仅是创建了我的消息传递变量,它会根据计时器的状态而变化,并区分计时器处于活动状态和暂停状态。这些状态对于创建与计时器倒计时相关的方法至关重要。

这些方法与按钮的连接非常自然。我需要为每个按钮附加一个点击时运行的方法。需求是四个按钮(开始、暂停、恢复和重置)。

开始按钮会开启倒计时,并进行timerRunning: true,因为计时器仍在运行。暂停按钮会冻结倒计时,并进行timerRunning: false。恢复按钮会以当前时间和步速重新开启倒计时,同时进行timerRunning: true。最后,重置按钮会将倒计时设置为起始数字,并进行timerRunning: false

这是与我们刚才讨论的功能相关的方法的原始代码。包括在某些状态下更改消息。

methods: {
    timerRun() {
      this.timerRunning = true;
      this.message = 'Greatness is within sight!!!';
    },
    timerPause() {
      this.message = 'Never quit, keep going!!';
      this.timerRunning = false;
    },
    timerReset() {
      this.message = 'Let the countdown begin!!';
      this.timerRunning = false;
    },
    timerCountdown() {
      this.timerRunning = true;
    }
  }
Enter fullscreen mode Exit fullscreen mode

为了更改某些步骤的消息,我将上面显示的方法绑定到下面显示的按钮上,这会触发不同的操作。根据按下的按钮,它可以显示“计时器正在运行”、“计时器已暂停”、“计时器已重置”或“计时器正在运行”。timerRunning使用 v-if 函数,随着场景的变化,当前显示的按钮配置也会发生变化。这样,按钮的功能就完成了,现在是时候让计时器真正开始工作了。

<div class="buttons">
      <button @click="timerRun" v-if="!timerRunning">Start</button>
      <button @click="timerPause" v-if="timerRunning">Pause</button>
      <button @click="timerReset" v-if="timerRunning">Restart</button>
</div>
Enter fullscreen mode Exit fullscreen mode

当我开始制作计时器时,我意识到我不太懂如何编写倒计时代码,也不理解创建计时器的基本原理。为了学习它的工作原理,我很快尝试制作一个时钟。

我学会了如何以毫秒为单位来执行所有时钟操作,如何逐步显示时间,以及如何显示小时、分钟、秒和毫秒。通过这个业余项目,我学到了很多关于时间管理的知识,比如如何快速前进或后退时间。

我在制作倒计时器时遇到的一个主要问题是时间会持续变化。刚开始制作倒计时器时,每次按下启动/恢复按钮后,倒计时都会逐渐加快。这不符合我的预期,也不利于后续需要恢复的操作。制作完这个时钟后,我找到了一种更一致的触发计时器启动的方法。

data {
    interval: null
},
methods: {
    timerRun() {
      this.timerRunning = true;
      this.message = 'Greatness is within sight!!!';
      this.interval = setInterval(this.countdownTimer, 1000);
    }
    timerPause() {
      this.message = 'Never quit, keep going!!';
      this.timerRunning = false;
      clearInterval(this.interval);
    },
    timerReset() {
      this.message = 'Let the countdown begin!!';
      this.timerRunning = false;
      clearInterval( () => { this.interval; });
    }
}
Enter fullscreen mode Exit fullscreen mode

这段代码对于确保倒计时从初始运行到后续恢复的一致性至关重要。现在,当计时器启动时,this.interval会启动一个新的计时器进行倒计时。暂停并重置时,该变量会被清除,从而暂停倒计时并阻止变量相互叠加。

要让计时器倒计时,我得先理解大量的数学知识,可惜我数学很差。最后,我需要把时间的单位分解成——小时是 60*60*60,分钟是 60*60,毫秒也是 60。所以你需要把毫秒和时间加起来。(如果我解释得不好,请见谅,我的数学很差)。

现在,倒计时的另一个问题是,如何避免出现负数。下面的解释解释了时间不会变成负数的原因(实际上它会变成负数,但我们没有显示出来)。

timerCountdown() {
      console.log('Working');
      this.timerRunning = true;
      this.interval = setInterval(this.updateCurrentTime, 1000);
      // Counts down from 60 seconds times 1000.
      setInterval( () => {
        this.timerMinutes--
      }, 60 * 1000)

      // Check if seconds at double zero and then make it a 59 to countdown from.
      // need another method of checking the number while in the loop and then adding a zero on the number under 10
      if(this.timerSeconds === '00'){
        this.timerSeconds = 59;
        setInterval( () => {
          this.timerSeconds--
        }, 1000);
      } else {
        setInterval( () => {
          this.timerSeconds--
        }, 1000);
      }
    },
Enter fullscreen mode Exit fullscreen mode

他的解决方案确实涉及到负数。你可以添加一个简单的检查,如果时间<= 0,就可以重置并停止计时器。至于如何让它保持在60秒,这仅仅是个数学问题。他将四舍五入后的分钟数转换成秒数,然后从总时间(以秒为单位)中减去。所以剩下的就是0到60之间的秒数。
这可以用模数来缩短和清除。
this.totalTime % 60
这样余数总是会落在0到60之间。
感谢Zammy13回答我的问题。

模数的细分(余数%)。

我的计时器需要 25 分钟,所以我用了这个totalTime: (25 * 60)。这等于总时间(25 分钟)乘以 60,也就是秒数。总时间就是 1500 秒。

computed: {
     time: function() {
      return this.minutes + " : " + this.seconds;
    },
    hours: function() {
      var milli = this.milliseconds;
      // var hrs = new Date().getHours();
      // Used getHours() since the below didn't work for me
      var hrs = Math.floor((milli / 3600000) % 24);
      if (hrs >= 13) { hrs = hrs - 12 }
      return hrs >= 10 ? hrs : '0' + hrs;
    },
    minutes: function() {
      var min = Math.floor(this.totalTime / 60);
      return min >= 10 ? min : '0' + min;
    },
    seconds: function() {
      var sec = this.totalTime - (this.minutes * 60);
      return sec >= 10 ? sec : '0' + sec;
    }
  }
Enter fullscreen mode Exit fullscreen mode

最后一步是确保你的计时器知道它正在倒计时。这可能是整个过程中最简单的部分,只需检查变量timerRunning == true,然后删除一毫秒即可。

countdownTimer() {
      if (this.timerRunning == true) {
          this.totalTime--;
      }
    }
Enter fullscreen mode Exit fullscreen mode

结尾

这条路很漫长,付出的努力也比我预想的要多得多。最终,我做了一个基础的东西,迫不及待地想做一个功能齐全的东西。它能告诉你番茄工作法的进展,还能让番茄工作法在视觉上更有趣。

挑战的最终代码笔

这个 Codepen 有很多问题,包括加速倒计时。我在我的个人版计时器中修复了这个问题。这样做是为了达到一个目标,那就是挑战截止日期。我自己的高级计时器将会有第二部分。

文章来源:https://dev.to/teekatwo/building-a-pomodoro-timer-with-vuejs-on-codepen-7no
PREV
8张照片展现的雄辩关系
NEXT
使用 root 权限运行 Kubernetes Pod(不推荐)