Countdown 倒计时
精准倒计时组件,核心调度基于系统绝对时间戳差值计算。当浏览器标签页从后台休眠唤醒时自适应校准,杜绝累积定时器漂移,并内置读屏高频降噪与到期通知。为保证 SSR 水合首帧一致,服务端和客户端初次渲染显示占位文本;读取浏览器时钟并启动计时从挂载后开始。
预览
安装
pnpm dlx brutx-vue@latest add countdown用法
<script setup>
import { onMounted, ref } from 'vue'
import { Countdown } from 'brutx-ui-vue'
const ONE_DAY_MS = 24 * 60 * 60 * 1000
const targetTime = ref<number | null>(null)
onMounted(() => {
targetTime.value = Date.now() + ONE_DAY_MS
})
</script>
<template>
<!-- 基础倒计时 -->
<Countdown title="剩余时间" :value="targetTime" />
<!-- 自定义时间格式与卡片变体 -->
<Countdown
title="活动截止"
:value="targetTime"
format="DD [天] HH [时] mm [分] ss [秒]"
variant="card"
/>
</template>SSR 首帧与自定义内容
SSR 和水合期间,组件会先显示 placeholder(默认 -),挂载后才按 value 目标时间计算剩余时间。默认插槽的 formatted 在准备完成前也是占位文本;这时 remaining 为 0、isFinished 为 false。isReady 会在挂载并完成首次计算后变为 true,此时 remaining 和 isFinished 才对应当前目标。
<Countdown :value="targetTime">
<template #default="{ formatted, isReady }">
{{ isReady ? formatted : '正在准备倒计时' }}
</template>
</Countdown>毫秒级刷新与格式化转义
在 format 格式化字符串中包含 SSS 时会自动以高频(~30fps)刷新毫秒。普通文本字符若包含保留标识(如 D、H、m、s)时,可用方括号 [...] 包裹转义:
<script setup>
import { onMounted, ref } from 'vue'
const ONE_MINUTE_MS = 60 * 1000
const targetTime = ref<number | null>(null)
onMounted(() => {
targetTime.value = Date.now() + ONE_MINUTE_MS
})
</script>
<template>
<Countdown
title="秒杀倒计时"
:value="targetTime"
format="mm:ss.SSS"
variant="card"
/>
</template>到期回调
通过 @finish 监听倒计时归零事件,通过 @change 监听剩余毫秒数变化:
<script setup>
import { onMounted, ref } from 'vue'
import { Countdown } from 'brutx-ui-vue'
const FIVE_SECONDS_MS = 5 * 1000
const targetTime = ref<number | null>(null)
onMounted(() => {
targetTime.value = Date.now() + FIVE_SECONDS_MS
})
function onFinish() {
console.log('倒计时结束!')
}
function onChange(remainingMs: number) {
console.log('剩余毫秒:', remainingMs)
}
</script>
<template>
<Countdown
:value="targetTime"
@finish="onFinish"
@change="onChange"
/>
</template>变体
| 变体 | 说明 |
|---|---|
default | 默认变体,轻量内联排版,无额外背景与边框 |
card | 粗野主义卡片,3px 黑色硬边框、硬阴影、内边距与圆角 |
bordered | 粗黑硬边框卡片,无投影 |
subtle | 浅色高亮背景卡片,带粗黑边框与硬阴影 |
<template>
<Countdown title="Default" :value="targetTime" variant="default" />
<Countdown title="Card" :value="targetTime" variant="card" />
<Countdown title="Bordered" :value="targetTime" variant="bordered" />
<Countdown title="Subtle" :value="targetTime" variant="subtle" />
</template>尺寸
| 尺寸 | 标题字号 | 数值字号 |
|---|---|---|
sm | text-xs | text-2xl |
default | text-sm | text-3xl sm:text-4xl |
lg | text-base | text-4xl sm:text-5xl |
<template>
<Countdown title="小型" :value="targetTime" size="sm" variant="card" />
<Countdown title="标准" :value="targetTime" size="default" variant="card" />
<Countdown title="大型" :value="targetTime" size="lg" variant="card" />
</template>导出类型
组件导出了变体函数与格式化解析工具函数:
import type {
CountdownProps,
CountdownValue,
CountdownEmits,
CountdownVariantProps,
} from 'brutx-ui-vue'
import {
countdownVariants,
parseCountdownTarget,
formatCountdown,
} from 'brutx-ui-vue'API 参考
| 名称 | 类型 | 默认值 | 说明 |
|---|---|---|---|
value可空 | CountdownValue | undefined | 倒计时的目标时间点,支持毫秒时间戳、Date、纯数字时间戳字符串及可解析的日期字符串;空值或无效日期显示占位文本。 |
详情声明类型CountdownValue 字面量
关联类型 CountdownValue 类型定义 — CountdownValueexport type CountdownValue = number | string | Date | null | undefined 默认值详情
来源packages/ui/src/components/countdown/types.ts | |||
format | string | undefined | "HH:mm:ss" | 剩余时间格式,支持 DD、D、HH、H、mm、m、ss、s、SSS、SS、S 和方括号转义文本。包含 S 时使用毫秒级刷新。 |
详情声明类型string | undefined 默认值详情
来源packages/ui/src/components/countdown/types.ts | |||
title | string | undefined | undefined | 显示在倒计时数值上方的标题文本,title 插槽可替换其内容。 |
详情声明类型string | undefined 默认值详情
来源packages/ui/src/components/countdown/types.ts | |||
prefix | string | undefined | undefined | 显示在倒计时数值前的文本,prefix 插槽可替换其内容。 |
详情声明类型string | undefined 默认值详情
来源packages/ui/src/components/countdown/types.ts | |||
suffix | string | undefined | undefined | 显示在倒计时数值后的文本,suffix 插槽可替换其内容。 |
详情声明类型string | undefined 默认值详情
来源packages/ui/src/components/countdown/types.ts | |||
placeholder | string | undefined | undefined运行时回退: | 挂载前或目标时间为空、无效时显示的占位文本。 |
详情声明类型string | undefined 默认值详情
来源packages/ui/src/components/countdown/types.ts | |||
variant | "bordered" | "card" | "default" | "subtle" | undefined | "default" | 倒计时外层容器的背景和边框变体。 |
详情声明类型NonNullable<"default" | "card" | "bordered" | "subtle" | null | undefined> | undefined 字面量
默认值详情
来源packages/ui/src/components/countdown/types.ts | |||
size | "default" | "lg" | "sm" | undefined | "default" | 传给内部 Statistic 的尺寸,控制数值与配套文字的大小。 |
详情声明类型NonNullable<"default" | "lg" | "sm" | null | undefined> | undefined 字面量
默认值详情
来源packages/ui/src/components/countdown/types.ts | |||
class | string | undefined | undefined | 合并到倒计时外层容器的自定义 CSS 类。 |
详情声明类型string | undefined 默认值详情
来源packages/ui/src/components/countdown/types.ts | |||
| 名称 | 签名或类型 | 说明 |
|---|---|---|
@change | [remaining: number] | 计时刷新或目标时间重新计算时发出剩余毫秒数,最小为零。 |
详情声明类型[remaining: number] 来源packages/ui/src/components/countdown/Countdown.vue | ||
@finish | [] | 有效倒计时进入完成状态时发出;挂载时目标已到期也会发出。新的未来目标会重新开始计时并允许再次完成。 |
详情声明类型[] 来源packages/ui/src/components/countdown/Countdown.vue | ||
| 名称 | 签名或类型 | 说明 |
|---|---|---|
#title | { title?: string | undefined; } | 自定义标题区域,接收 title 属性值;默认显示该文本。 |
详情声明类型{ title?: string | undefined; }来源packages/ui/src/components/countdown/Countdown.vue | ||
#prefix | { prefix?: string | undefined; } | 自定义数值前缀区域,接收 prefix 属性值。 |
详情声明类型{ prefix?: string | undefined; }来源packages/ui/src/components/countdown/Countdown.vue | ||
#suffix | { suffix?: string | undefined; } | 自定义数值后缀区域,接收 suffix 属性值。 |
详情声明类型{ suffix?: string | undefined; }来源packages/ui/src/components/countdown/Countdown.vue | ||
#default | { remaining: number; formatted: string; isFinished: boolean; isReady: boolean; } | 自定义数值区域,接收剩余毫秒数、格式化字符串、是否完成及是否已挂载的 isReady 状态。 |
详情声明类型{ remaining: number; formatted: string; isFinished: boolean; isReady: boolean; }来源packages/ui/src/components/countdown/Countdown.vue | ||
可访问性
- 键盘操作:时序展示类组件,不捕获键盘输入;嵌套在交互区块中时,焦点遵循 DOM 正常流转。
- ARIA 属性:高频走字期间保持
aria-live静默,防止屏幕阅读器频繁读秒骚扰用户;倒计时到达零值时通过aria-live="polite"触发一次性完成语音通知。 - 焦点管理:无内部模态或焦点锁定,不干预辅助技术正常光标导航。
- 数字排版:使用等宽数字(
font-mono)减少更新时的宽度变化。剩余时间依据当前时钟计算,计时调度在挂载后启动;自定义默认插槽可用isReady区分占位首帧与已计算状态。