| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899 |
- <template>
- <div class="time-counter">
- {{ formattedTime }}
- </div>
- </template>
- <script>
- export default {
- name: 'TimeClock',
- // props 定义(与 Vue3 逻辑一致,保留非负整数校验)
- props: {
- initialSeconds: {
- type: Number,
- required: true,
- validator(value) {
- // 校验:必须是非负整数
- return Number.isInteger(value) && value >= 0
- }
- }
- },
- data() {
- return {
- // 基础毫秒(作为起点)
- baseMillis: Math.floor(this.initialSeconds),
- // 启动时间戳(用于计算增量)
- startTs: Date.now(),
- // 全局tick推送的当前时间(订阅更新)
- nowTs: Date.now()
- }
- },
- computed: {
- // 格式化时间:毫秒 → 00:00:00.00 格式(毫秒两位)
- formattedTime() {
- 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 minutes = String(Math.floor((totalMs % 3600000) / 60000)).padStart(2, '0')
- const seconds = String(Math.floor((totalMs % 60000) / 1000)).padStart(2, '0')
- // const ms2 = String(Math.floor((totalMs % 1000) / 10)).padStart(2, '0')
- return `${hours}:${minutes}:${seconds}`
- }
- },
- watch: {
- // 监听初始秒数变化(对应 Vue3 的 watch 函数)
- initialSeconds: {
- handler(newVal) {
- // 同步为毫秒值并重置起点
- const safeVal = Number(newVal)
- this.baseMillis = Number.isFinite(safeVal) ? Math.floor(safeVal) : 0
- this.startTs = Date.now()
- },
- immediate: true
- }
- },
- methods: {
- // 订阅全局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 初始化逻辑)
- mounted() {
- this._unsub = this.subscribeTick()
- },
- // 组件卸载时清理定时器(避免内存泄漏,与 Vue3 一致)
- beforeDestroy() {
- if (this._unsub) this._unsub()
- }
- }
- </script>
- <style scoped>
- .time-counter {
- font-size: 14px;
- font-weight: 600;
- color: #ff0000;
- letter-spacing: 2px;
- }
- </style>
|