50天50个小项目 (Vue3 + Tailwindcss V4) ✨ | ThemeClock(主题时钟)

📅 我们继续 50 个小项目挑战!—— ThemeClock组件

仓库地址:https://github.com/SunACong/50-vue-projects

项目预览地址:https://50-vue-projects.vercel.app/

在这里插入图片描述


使用 Vue 3 的 Composition API 和 <script setup> 语法结合 TailwindCSS 构建一个能够动态切换主题(深色与浅色)的时钟组件。该组件不仅显示当前时间(包括小时、分钟和秒),还展示了今天的日期和星期。


🎯 组件目标

  • 动态切换主题(深色/浅色)
  • 显示当前的时间(小时、分钟、秒针)
  • 展示今日日期和星期
  • 使用 CSS 变换实现指针旋转效果
  • 基于 Vue 3 和 TailwindCSS 实现响应式设计

⚙️ 技术实现点

技术点描述
Vue 3 Composition API (<script setup>)使用响应式变量管理组件状态
ref 响应式变量控制时间状态、主题模式
onMountedonUnmounted 生命周期钩子定时更新时间状态
TailwindCSS 自定义样式快速构建现代 UI 界面
@click 事件绑定切换主题逻辑

🧱 组件实现

模板结构 <template>

<template><div:class="['min-h-screen',theme === 'dark' ? 'bg-gray-900 text-white' : 'bg-gray-100 text-gray-900','flex flex-col items-center justify-center',]"><!-- 主题切换按钮 --><button@click="toggleTheme":class="['mb-8 rounded-md p-2',theme === 'dark' ? 'bg-gray-700 hover:bg-gray-600' : 'bg-white hover:bg-gray-200',]">{{ theme === 'dark' ? '切换至浅色主题' : '切换至深色主题' }}</button><!-- 时钟容器 --><div class="relative h-64 w-64"><!-- 表盘 --><div:class="['absolute inset-0 rounded-full',theme === 'dark' ? 'bg-gray-800' : 'bg-white',]"><!-- 时针、分针、秒针及中心圆点 --><!-- ... (省略部分代码) ... --></div></div><!-- 日期与星期 --><div:class="['mt-8 text-xl font-semibold',theme === 'dark' ? 'text-gray-300' : 'text-gray-800',]">{{ currentDate }} {{ currentDay }}</div></div>
</template>

脚本逻辑 <script setup>

<script setup>
import { ref, onMounted, onUnmounted } from 'vue'// 主题切换
const theme = ref('dark')
const toggleTheme = () => {theme.value = theme.value === 'dark' ? 'light' : 'dark'
}// 时间状态
const hoursRotation = ref(0)
const minutesRotation = ref(0)
const secondsRotation = ref(0)
const currentDate = ref('')
const currentDay = ref('')// 更新时间函数
const updateTime = () => {const now = new Date()const hours = now.getHours()const minutes = now.getMinutes()const seconds = now.getSeconds()const hoursForClock = hours % 12hoursRotation.value = hoursForClock * 30 + minutes * 0.5minutesRotation.value = minutes * 6 + seconds * 0.1secondsRotation.value = seconds * 6console.log(hoursRotation.value, minutesRotation.value, secondsRotation.value)const days = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六']currentDate.value = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')}`currentDay.value = days[now.getDay()]
}// 启动定时器
let interval = null
onMounted(() => {updateTime()interval = setInterval(updateTime, 1000)
})// 清除定时器
onUnmounted(() => {clearInterval(interval)
})
</script>

🔍 重点效果实现

✅ 动态主题切换

通过 theme 变量来控制整个应用的主题,并且根据其值动态修改类名:

:style="{transform: `translateY(-50%) rotate(${hoursRotation - 90}deg)`,
}"

当用户点击“切换主题”按钮时,调用 toggleTheme() 方法切换主题模式。

💡 指针旋转动画

使用 CSS 变换来实现指针的旋转效果。例如,时针的旋转角度计算如下:

hoursRotation.value = hoursForClock * 30 + minutes * 0.5

每个小时对应的角度是 30 度(360度/12小时),并且为了更加精确,我们还会加上由分钟数决定的部分角度。

🖼️ 日期与星期展示

利用 JavaScript 的 Date 对象获取当前的日期和星期,然后以友好的格式展示给用户:

currentDate.value = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()
).padStart(2, '0')}`
currentDay.value = days[now.getDay()]

你说得对,让我们补充一下 🎨 TailwindCSS 样式重点讲解 部分,详细解释在这个时钟组件中使用的 TailwindCSS 类及其作用。


🎨 TailwindCSS 样式重点讲解

以下是针对该时钟组件所用到的 TailwindCSS 工具类的详细解释:

类名作用
min-h-screen设置最小高度为视口高度,确保组件至少占据整个屏幕的高度。
bg-gray-900 text-white / bg-gray-100 text-gray-900分别设置背景颜色和文本颜色,前者用于深色主题,后者用于浅色主题。
flex flex-col items-center justify-center使用 Flexbox 布局,使内容垂直和水平居中,并按列排列。
mb-8 rounded-md p-2外边距底部设为 mb-8,圆角设为 rounded-md,内边距设为 p-2
bg-gray-700 hover:bg-gray-600 / bg-white hover:bg-gray-200按钮的背景颜色及悬停时的颜色变化,分别对应深色和浅色主题下的样式。
relative h-64 w-64设置相对定位,宽高均为 64 单位,用于创建一个固定大小的表盘容器。
absolute inset-0 rounded-full绝对定位并铺满父容器,同时将元素裁剪成圆形。
h-1 w-1/4 origin-left rounded-full bg-current定义时针的宽度、长度、旋转中心点以及圆角样式。bg-current 表示使用当前元素的文字颜色作为背景颜色。
translateY(-50%) rotate(${hoursRotation - 90}deg)利用 CSS 变换函数调整指针的位置和旋转角度。
h-px w-1/2 origin-left rounded-full bg-red-500秒针的特殊样式,其中 h-px 创建了一个极细的秒针,bg-red-500 设置了红色。
h-3 w-3 -translate-x-1/2 -translate-y-1/2 transform rounded-full中心圆点的样式,通过平移将其精确放置在表盘中心。
text-xl font-semibold设置日期与星期部分的字体大小和粗细。
text-gray-300 / text-gray-800根据主题模式设置日期与星期部分的文本颜色。

📁 常量定义 + 组件路由

constants/index.js 添加组件预览常量:

{id: 19,title: 'Theme Clock',image: 'https://50projects50days.com/img/projects-img/19-theme-clock.png',link: 'ThemeClock',},

router/index.js 中添加路由选项:

{path: '/ThemeClock',name: 'ThemeClock',component: () => import('@/projects/ThemeClock.vue'),},

📁 扩展功能

此组件可以进一步扩展的功能包括:

  • 自定义表盘样式:可以根据个人喜好调整表盘的颜色、大小等。
  • 添加闹钟或倒计时功能:为时钟组件增加实用功能。
  • 国际化支持:支持多语言,特别是日期和星期的本地化。
  • 响应式设计:优化不同屏幕尺寸下的显示效果。

🏁 总结

👉 下一篇,我们将完成ButtonRippleEffect组件,一个简单的按钮组件,点击有水波的效果。🚀