vue记录时长前端实现
Vue 前端实现时长记录功能
核心思路
通过 Vue 的响应式数据和生命周期钩子,结合浏览器 API 实现开始、暂停、继续和重置时长的功能。关键点在于利用 setInterval 计时并实时更新显示。
基础实现代码
<template>
<div>
<p>已记录时长: {{ formattedTime }}</p>
<button @click="startTimer">开始</button>
<button @click="pauseTimer">暂停</button>
<button @click="resetTimer">重置</button>
</div>
</template>
<script>
export default {
data() {
return {
seconds: 0,
timer: null,
isRunning: false
}
},
computed: {
formattedTime() {
const hours = Math.floor(this.seconds / 3600)
const minutes = Math.floor((this.seconds % 3600) / 60)
const secs = this.seconds % 60
return `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`
}
},
methods: {
startTimer() {
if (!this.isRunning) {
this.isRunning = true
this.timer = setInterval(() => {
this.seconds++
}, 1000)
}
},
pauseTimer() {
clearInterval(this.timer)
this.isRunning = false
},
resetTimer() {
clearInterval(this.timer)
this.seconds = 0
this.isRunning = false
}
},
beforeUnmount() {
clearInterval(this.timer)
}
}
</script>
进阶功能实现
持久化存储
结合 localStorage 实现刷新页面不丢失记录:
mounted() {
const savedTime = localStorage.getItem('recordedTime')
if (savedTime) {
this.seconds = parseInt(savedTime)
}
},
watch: {
seconds(newVal) {
localStorage.setItem('recordedTime', newVal.toString())
}
}
多段时长记录
记录多个时间段并统计总时长:
data() {
return {
timeSegments: [],
currentStart: null
}
},
methods: {
startSegment() {
this.currentStart = new Date()
},
endSegment() {
if (this.currentStart) {
const duration = Math.floor((new Date() - this.currentStart) / 1000)
this.timeSegments.push(duration)
this.currentStart = null
}
},
totalDuration() {
return this.timeSegments.reduce((sum, seg) => sum + seg, 0)
}
}
性能优化方案
使用 requestAnimationFrame
替代 setInterval 实现更精确的计时:
methods: {
startTimer() {
if (!this.isRunning) {
this.isRunning = true
const startTime = Date.now() - this.seconds * 1000
const update = () => {
this.seconds = Math.floor((Date.now() - startTime) / 1000)
if (this.isRunning) {
requestAnimationFrame(update)
}
}
requestAnimationFrame(update)
}
}
}
Worker 线程计时
避免主线程阻塞:

// worker.js
let timer
self.onmessage = function(e) {
if (e.data === 'start') {
let seconds = 0
timer = setInterval(() => {
self.postMessage(++seconds)
}, 1000)
} else if (e.data === 'stop') {
clearInterval(timer)
}
}
// Vue组件
created() {
this.worker = new Worker('./worker.js')
this.worker.onmessage = (e) => {
this.seconds = e.data
}
}
注意事项
- 页面隐藏时(切换标签页)建议暂停计时,可通过
document.visibilityState监听 - 移动端需注意锁屏情况,推荐使用 Background Timer 等插件
- 长时间运行需考虑数字溢出问题,建议使用 BigInt 或分段记录
以上方案可根据实际需求组合使用,基础实现已能满足多数场景,进阶功能适合需要精确统计或离线保存的场景。






