📅 我们继续 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 响应式变量 | 控制时间状态、主题模式 |
onMounted 和 onUnmounted 生命周期钩子 | 定时更新时间状态 |
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
组件,一个简单的按钮组件,点击有水波的效果。🚀