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

发布于:2025-07-01 ⋅ 阅读:(18) ⋅ 点赞:(0)

📅 我们继续 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 % 12
    hoursRotation.value = hoursForClock * 30 + minutes * 0.5
    minutesRotation.value = minutes * 6 + seconds * 0.1
    secondsRotation.value = seconds * 6

    console.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组件,一个简单的按钮组件,点击有水波的效果。🚀