<template> <span class="zjobosdg"> <span v-text="hh"></span> <span class="colon" :class="{ showColon }">:</span> <span v-text="mm"></span> <span v-if="showS" class="colon" :class="{ showColon }">:</span> <span v-if="showS" v-text="ss"></span> <span v-if="showMs" class="colon" :class="{ showColon }">:</span> <span v-if="showMs" v-text="ms"></span> </span> </template> <script lang="ts" setup> import { onUnmounted, ref, watch } from 'vue'; const props = withDefaults(defineProps<{ showS?: boolean; showMs?: boolean; offset?: number; }>(), { showS: true, showMs: false, offset: 0 - new Date().getTimezoneOffset(), }); let intervalId; const hh = ref(''); const mm = ref(''); const ss = ref(''); const ms = ref(''); const showColon = ref(false); let prevSec: number | null = null; watch(showColon, (v) => { if (v) { window.setTimeout(() => { showColon.value = false; }, 30); } }); const tick = () => { const now = new Date(); now.setMinutes(now.getMinutes() + (new Date().getTimezoneOffset() + props.offset)); hh.value = now.getHours().toString().padStart(2, '0'); mm.value = now.getMinutes().toString().padStart(2, '0'); ss.value = now.getSeconds().toString().padStart(2, '0'); ms.value = Math.floor(now.getMilliseconds() / 10).toString().padStart(2, '0'); if (now.getSeconds() !== prevSec) showColon.value = true; prevSec = now.getSeconds(); }; tick(); watch(() => props.showMs, () => { if (intervalId) window.clearInterval(intervalId); intervalId = window.setInterval(tick, props.showMs ? 10 : 1000); }, { immediate: true }); onUnmounted(() => { window.clearInterval(intervalId); }); </script> <style lang="scss" scoped> .zjobosdg { > .colon { opacity: 0; transition: opacity 1s ease; &.showColon { opacity: 1; transition: opacity 0s; } } } </style>