JavaScript 已禁用

为了获得更好的体验,请启用JavaScript,或点击下方链接跳转:

跳转至百度
Skip to content

右键菜单

此组件是一个时钟组件,适合放置在导航栏等位置

Clock.vue

vue
<template>
  <div id="clock">
    <div class="time">
      <span class="hour">{{ hours }}</span>
      <span class="separator">:</span>
      <span class="minute">{{ minutes }}</span>
      <span class="separator">:</span>
      <span class="second">{{ seconds }}</span>
    </div>
  </div>
</template>

<script setup lang="ts">
import { onMounted, onUnmounted, shallowRef } from "vue";

// 定时器管理
const timerID = shallowRef<number | null>(null);

// 时间状态 - 拆分小时、分钟、秒
const hours = shallowRef<string>("");
const minutes = shallowRef<string>("");
const seconds = shallowRef<string>("");

// 数字补零函数
function zeroPadding(num: number, digit: number): string {
  return String(num).padStart(digit, "0");
}

// 立即更新时间的函数
function updateTime() {
  const now = new Date();
  seconds.value = zeroPadding(now.getSeconds(), 2);

  // 分钟和小时变化频率低,单独判断更新
  const currentMinutes = now.getMinutes();
  if (currentMinutes !== parseInt(minutes.value)) {
    minutes.value = zeroPadding(currentMinutes, 2);
  }

  const currentHours = now.getHours();
  if (currentHours !== parseInt(hours.value)) {
    hours.value = zeroPadding(currentHours, 2);
  }
}

// 动画循环函数
function animateClock() {
  updateTime(); // 每次帧更新都刷新时间(确保秒级精度)
  timerID.value = requestAnimationFrame(animateClock);
}

// 初始化时钟
const initClock = () => {
  if (timerID.value !== null) {
    cancelAnimationFrame(timerID.value);
  }
  updateTime(); // 初始化时立即执行一次(解决初始显示问题)
  timerID.value = requestAnimationFrame(animateClock);
};

onMounted(() => {
  // 组件挂载时立即初始化并更新时间
  initClock();
});

// 组件卸载时清理
onUnmounted(() => {
  if (timerID.value !== null) {
    cancelAnimationFrame(timerID.value);
  }
});
</script>

<style scoped lang="scss">
#clock {
  order: 99;
  text-align: center;
  margin-left: 15px;
  display: flex;
  align-items: center;

  .time {
    /* 隔离渲染范围 */
    contain: content;
    letter-spacing: 0.05em;
    font-size: 16px;
    font-weight: bold;
  }

  .time span {
    /* 将每个部分用 inline-block 包裹,形成独立“绘制单元”,避免局部更新,整个重绘的问题 */
    display: inline-block;
  }
}

/* 视口宽度 ≤ 767px 时生效(移动端),调整时间显示位置 */
@media (max-width: 767px) {
  // 移动端导航栏吸顶
  #clock {
    order: 0;
  }
}

/* 父级有.full-img-nav-bar类时的样式(Banner范围内) */
:deep(.full-img-nav-bar #clock) {
  color: var(--vp-c-white);
  text-shadow:
    0 0 20px rgba(10, 175, 230, 1),
    0 0 20px rgba(10, 175, 230, 0);

  /* 暗色模式下的样式 */
  /*  :deep(html.dark .full-img-nav-bar #clock) {
    color: #b9199b;
  }*/
}

/* 父级没有.full-img-nav-bar类时的样式(滚动离开Banner后) */
:deep(:not(.full-img-nav-bar) #clock) {
  color: var(--vp-c-text-1);
  text-shadow: none;

  /* 暗色模式下的样式 */
  /*  :deep(html.dark :not(.full-img-nav-bar) #clock) {
    color: #daf6ff;
  }*/
}
</style>

作者:威威

版权:此文章版权归 威威 所有,如有转载,请注明出处!

链接:可点击右上角分享此页面复制文章链接

最后更新于:

最近更新