|
@@ -20,54 +20,71 @@ export default {
|
|
|
},
|
|
},
|
|
|
data() {
|
|
data() {
|
|
|
return {
|
|
return {
|
|
|
- // 当前累计毫秒
|
|
|
|
|
- currentMillis: Math.floor(this.initialSeconds),
|
|
|
|
|
- // 定时器实例(用于清理)
|
|
|
|
|
- timer: null
|
|
|
|
|
|
|
+ // 基础毫秒(作为起点)
|
|
|
|
|
+ baseMillis: Math.floor(this.initialSeconds),
|
|
|
|
|
+ // 启动时间戳(用于计算增量)
|
|
|
|
|
+ startTs: Date.now(),
|
|
|
|
|
+ // 全局tick推送的当前时间(订阅更新)
|
|
|
|
|
+ nowTs: Date.now()
|
|
|
}
|
|
}
|
|
|
},
|
|
},
|
|
|
computed: {
|
|
computed: {
|
|
|
- // 格式化时间:毫秒 → 00:00:00.000 格式
|
|
|
|
|
|
|
+ // 格式化时间:毫秒 → 00:00:00.00 格式(毫秒两位)
|
|
|
formattedTime() {
|
|
formattedTime() {
|
|
|
- const totalMs = this.currentMillis
|
|
|
|
|
|
|
+ const elapsed = this.baseMillis + (this.nowTs - this.startTs)
|
|
|
|
|
+ const totalMs = Math.max(0, Math.floor(elapsed))
|
|
|
const hours = String(Math.floor(totalMs / 3600000)).padStart(2, '0')
|
|
const hours = String(Math.floor(totalMs / 3600000)).padStart(2, '0')
|
|
|
const minutes = String(Math.floor((totalMs % 3600000) / 60000)).padStart(2, '0')
|
|
const minutes = String(Math.floor((totalMs % 3600000) / 60000)).padStart(2, '0')
|
|
|
const seconds = String(Math.floor((totalMs % 60000) / 1000)).padStart(2, '0')
|
|
const seconds = String(Math.floor((totalMs % 60000) / 1000)).padStart(2, '0')
|
|
|
- const milliseconds = String(totalMs % 1000).padStart(3, '0')
|
|
|
|
|
- return `${hours}:${minutes}:${seconds}.${milliseconds}`
|
|
|
|
|
|
|
+ // const ms2 = String(Math.floor((totalMs % 1000) / 10)).padStart(2, '0')
|
|
|
|
|
+ return `${hours}:${minutes}:${seconds}`
|
|
|
}
|
|
}
|
|
|
},
|
|
},
|
|
|
watch: {
|
|
watch: {
|
|
|
// 监听初始秒数变化(对应 Vue3 的 watch 函数)
|
|
// 监听初始秒数变化(对应 Vue3 的 watch 函数)
|
|
|
initialSeconds: {
|
|
initialSeconds: {
|
|
|
handler(newVal) {
|
|
handler(newVal) {
|
|
|
- // 同步为毫秒值并重启计时
|
|
|
|
|
|
|
+ // 同步为毫秒值并重置起点
|
|
|
const safeVal = Number(newVal)
|
|
const safeVal = Number(newVal)
|
|
|
- this.currentMillis = Number.isFinite(safeVal) ? Math.floor(safeVal) : 0
|
|
|
|
|
- this.startTimer() // 重启定时器
|
|
|
|
|
|
|
+ this.baseMillis = Number.isFinite(safeVal) ? Math.floor(safeVal) : 0
|
|
|
|
|
+ this.startTs = Date.now()
|
|
|
},
|
|
},
|
|
|
immediate: true
|
|
immediate: true
|
|
|
}
|
|
}
|
|
|
},
|
|
},
|
|
|
methods: {
|
|
methods: {
|
|
|
- // 启动计时(毫秒级递增)
|
|
|
|
|
- startTimer() {
|
|
|
|
|
- // 清除已有定时器,避免重复计时
|
|
|
|
|
- if (this.timer) clearInterval(this.timer)
|
|
|
|
|
- // 每 10ms 递增 10 毫秒(兼顾性能与精度)
|
|
|
|
|
- const step = 10
|
|
|
|
|
- this.timer = setInterval(() => {
|
|
|
|
|
- this.currentMillis += step
|
|
|
|
|
- }, step)
|
|
|
|
|
|
|
+ // 订阅全局tick(单例定时器,所有实例共享,降低性能开销)
|
|
|
|
|
+ subscribeTick() {
|
|
|
|
|
+ const scope = globalThis.__timeClockScope || (globalThis.__timeClockScope = {
|
|
|
|
|
+ subs: new Set(),
|
|
|
|
|
+ timer: null
|
|
|
|
|
+ })
|
|
|
|
|
+ const cb = () => { this.nowTs = Date.now() }
|
|
|
|
|
+ scope.subs.add(cb)
|
|
|
|
|
+ if (!scope.timer) {
|
|
|
|
|
+ // 每秒触发一次,保持跳秒显示与两位毫秒展示
|
|
|
|
|
+ scope.timer = setInterval(() => {
|
|
|
|
|
+ const now = Date.now()
|
|
|
|
|
+ scope.subs.forEach(fn => fn(now))
|
|
|
|
|
+ }, 1000)
|
|
|
|
|
+ }
|
|
|
|
|
+ // 返回取消订阅函数
|
|
|
|
|
+ return () => {
|
|
|
|
|
+ scope.subs.delete(cb)
|
|
|
|
|
+ if (scope.subs.size === 0 && scope.timer) {
|
|
|
|
|
+ clearInterval(scope.timer)
|
|
|
|
|
+ scope.timer = null
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
},
|
|
},
|
|
|
// 初始化时启动计时(对应 Vue3 的 setup 初始化逻辑)
|
|
// 初始化时启动计时(对应 Vue3 的 setup 初始化逻辑)
|
|
|
mounted() {
|
|
mounted() {
|
|
|
- this.startTimer()
|
|
|
|
|
|
|
+ this._unsub = this.subscribeTick()
|
|
|
},
|
|
},
|
|
|
// 组件卸载时清理定时器(避免内存泄漏,与 Vue3 一致)
|
|
// 组件卸载时清理定时器(避免内存泄漏,与 Vue3 一致)
|
|
|
beforeDestroy() {
|
|
beforeDestroy() {
|
|
|
- if (this.timer) clearInterval(this.timer)
|
|
|
|
|
|
|
+ if (this._unsub) this._unsub()
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
</script>
|
|
</script>
|