📅 我们继续 50 个小项目挑战!—— IncrementingCounter
组件
仓库地址:https://github.com/SunACong/50-vue-projects
项目预览地址:https://50-vue-projects.vercel.app/
使用 Vue 3 的 Composition API 和 <script setup>
语法结合 TailwindCSS 构建一个带有数字增长动画效果的统计卡片组件。该组件常用于展示社交媒体粉丝数、网站访问量、销售数据等可视化指标。
🎯 组件目标
- 展示多个统计数据项(如 Twitter 关注者、YouTube 订阅数等)。
- 数字从
0
动态增长到指定目标值。 - 使用图标与文字搭配提升视觉识别度。
- 使用 TailwindCSS 快速构建现代 UI 界面。
- 添加生命周期控制防止内存泄漏。
⚙️ 技术实现点
技术点 | 描述 |
---|---|
Vue 3 Composition API (<script setup> ) |
使用响应式变量管理组件状态 |
reactive() 响应式数组 |
存储并更新多个统计项数据 |
onMounted 生命周期钩子 |
在组件挂载后启动动画 |
setInterval 定时器 |
控制数字逐步递增的过程 |
clearInterval |
避免内存泄漏,在组件卸载时清除定时器 |
TailwindCSS 布局与样式 | 快速构建美观的统计卡片界面 |
🧱 组件实现
模板结构 <template>
<template>
<div class="flex h-screen items-center justify-center gap-20 text-white">
<div
class="flex flex-col items-center justify-center gap-2"
v-for="item in iconList"
:key="item.id">
<img :src="item.icon" alt="icon" class="h-20 w-20" />
<div class="text-3xl font-extrabold">{{ item.count }}</div>
<div class="font-mono">{{ item.name }}</div>
</div>
</div>
</template>
脚本逻辑 <script setup>
<script setup>
import { ref, onMounted, onUnmounted, reactive } from 'vue'
const iconList = reactive([
{
id: 1,
name: 'Twitter Followers',
count: 0,
icon: '/src/assets/icon/推特.svg',
target: 12000,
},
{
id: 2,
name: 'Facebook Fans',
count: 0,
icon: '/src/assets/icon/facebook.svg',
target: 5000,
},
{
id: 3,
name: 'YouTube Subscribers',
count: 0,
icon: '/src/assets/icon/油管.svg',
target: 7000,
},
])
onMounted(() => {
const totalSteps = 100 // 总步数
const intervalDuration = 10 // 每次间隔时间(毫秒)
let currentStep = 0
const interval = setInterval(() => {
currentStep++
iconList.forEach((item) => {
const stepValue = Math.ceil(item.target / totalSteps) // 每步增长的值
item.count = Math.min(item.count + stepValue, item.target) // 确保不超过目标值
})
if (currentStep >= totalSteps) {
clearInterval(interval)
}
}, intervalDuration)
onUnmounted(() => {
clearInterval(interval)
})
})
</script>
🔍 重点效果实现
✅ 数字增长动画原理
通过 setInterval
设置了一个定时器,每 10ms 执行一次:
iconList.forEach((item) => {
const stepValue = Math.ceil(item.target / totalSteps)
item.count = Math.min(item.count + stepValue, item.target)
})
- 将目标值平均分成
totalSteps
步; - 每次增加一步的数值;
- 最终达到目标值,并停止计时器。
这样就能实现一个平滑的数字增长动画。
💡 组件卸载清理机制
为避免内存泄漏,我们在 onUnmounted
中调用 clearInterval
:
onUnmounted(() => {
clearInterval(interval)
})
确保组件卸载时自动清除定时器。
🎨 TailwindCSS 样式重点讲解
类名 | 作用 |
---|---|
flex , items-center , justify-center |
居中布局整个容器 |
h-screen |
高度为视口全高 |
gap-20 |
元素之间间距为 5rem |
flex-col |
设置为纵向排列 |
h-20 , w-20 |
图标大小为 5rem × 5rem |
text-3xl |
字体大小为 1.875rem |
font-extrabold |
加粗字体 |
font-mono |
使用等宽字体 |
text-white |
设置文字颜色为白色 |
这些 Tailwind 工具类帮助我们快速构建了一个视觉清晰、层次分明的统计信息展示区域。
📁 常量定义 + 组件路由
✅ 常量定义(可选)
constants/index.js
添加组件预览常量:
{
id: 15,
title: 'Incrementing Counter',
image: 'https://50projects50days.com/img/projects-img/15-incrementing-counter.png',
link: 'IncrementingCounter',
},
router/index.js
中添加路由选项:
{
path: '/IncrementingCounter',
name: 'IncrementingCounter',
component: () => import('@/projects/IncrementingCounter.vue'),
}
🏁 总结
数据统计卡片组件涵盖了Vue 3 的响应式系统、定时器控制、生命周期管理和 TailwindCSS 的灵活样式组合。
👉 下一篇,我们将完成DrinkWater
组件,一个交互式的喝水记录以及达成目标的组件,具有丝滑的交互动画!🚀