Pinia Getters 通过纯计算逻辑将毫秒级 remainingMs 格式化为 hh:mm:ss 字符串,确保响应式、零重复计算且不破坏缓存;需配合 actions 中的 visibility 校准,并支持多实例与可配置格式。

Pinia Getters 处理倒计时剩余时间的格式化,核心是把「毫秒级剩余时间」转为可读字符串(如 01:23:45),同时保持响应式、零重复计算、不破坏缓存机制。
用纯计算逻辑封装 formatTime
在 Store 的 getters 中定义一个只依赖 remainingMs 的格式化函数,不调用 Date.now()、不发起请求、不返回新对象引用:
- 接收 state 中的
remainingMs: number(单位:毫秒)作为唯一输入 - 内部做除法取整:小时 =
Math.floor(remainingMs / 3600000),分钟 =Math.floor((remainingMs % 3600000) / 60000),秒 =Math.floor((remainingMs % 60000) / 1000) - 每位补零用
.toString().padStart(2, '0'),拼接成hh:mm:ss字符串 - 避免返回
{ h, m, s }对象——那会每次新建引用,导致组件误判更新
示例:
export const useCountdownStore = defineStore('countdown', {<br>
state: () => ({<br>
remainingMs: 0,<br>
targetTime: 0 // 毫秒时间戳<br>
}),<br>
getters: {<br>
formattedTime: (state) => {<br>
const ms = Math.max(0, state.remainingMs);<br>
const h = Math.floor(ms / 3600000);<br>
const m = Math.floor((ms % 3600000) / 60000);<br>
const s = Math.floor((ms % 60000) / 1000);<br>
return `${h.toString().padStart(2, '0')}:${m.toString().padStart(2, '0')}:${s.toString().padStart(2, '0')}`;<br>
}<br>
}<br>
});
配合状态校准,确保格式始终准确
格式化本身不解决时间漂移,但 getters 要和 store 的校准逻辑协同:
- 当页面从后台切回或 visibilityState 变为 visible 时,在 actions 中重新计算
remainingMs = Math.max(0, targetTime - Date.now()) - 这个新值写入 state,getter 自动触发重算,
formattedTime立即更新 - 不需要在 getter 里手动判断 visibility —— 那会引入非响应式依赖,破坏缓存
支持多实例且格式可配置
如果一个页面有多个倒计时(如考试主计时 + 题目小计时),用工厂函数创建独立 store 实例,每个实例拥有自己的 formattedTime getter:
- 定义
useCountdown(id: string)工厂,内部用id隔离 state 和 getter - 可在 getter 中加参数支持不同格式:
formatTime: (state) => (showHours = true) => { ... },调用时store.formatTime(false)输出 mm:ss - 注意:带参 getter 不自动缓存不同参数结果,高频使用建议搭配 memoize 或拆分为多个固定 getter(如
timeMMSS、timeHHMMSS)










