Vue聊天应用单定时器批量更新消息时间差显示方案咨询
解决方案
要实现单个定时器更新所有消息的时间文本,核心思路是通过一个响应式触发标记,让所有依赖时间格式化的组件自动重新计算,具体步骤如下:
1. 修改Pinia Store,添加定时刷新机制
在聊天Store中添加一个响应式变量作为刷新触发点,同时设置单个定时器每隔60秒更新这个变量:
// @/stores/modules/chat.ts import { defineStore } from 'pinia'; import { ref, onUnmounted } from 'vue'; export const useChatStore = defineStore('chat', () => { // 响应式触发标记,值变化时会触发所有依赖它的计算更新 const timeRefreshTrigger = ref(0); let refreshTimer: number | null = null; // 启动定时刷新:每60秒更新触发标记 const startRefreshTimer = () => { refreshTimer = window.setInterval(() => { timeRefreshTrigger.value++; // 只要值变化,就能触发依赖更新 }, 60000); }; // 停止定时器,防止内存泄漏 const stopRefreshTimer = () => { if (refreshTimer) { clearInterval(refreshTimer); refreshTimer = null; } }; // 初始化时启动定时器 startRefreshTimer(); // Store销毁时清理定时器 onUnmounted(() => { stopRefreshTimer(); }); // 保留你原有的格式化函数 const getFormattedTime = (dateString: string): string => { const date = new Date(dateString); const now = new Date(); const diff = Math.abs(now - date) / 1000; // 差值(秒) if (diff < 60) { return this.localizedString("timeFormat.now"); } else if (diff < 120) { return this.localizedString("timeFormat.1MinuteAgo"); } else if (diff < 300) { return this.localizedString("timeFormat.5MinutesAgo"); } else if (diff < 1800) { const minutes = Math.floor(diff / 60); return this.localizedString("timeFormat.XMinutesAgo", [minutes]); } else if (this.time_isSameDay(now, date)) { return this.localizedString("timeFormat.today") + ", " + this.time_formatTime(date); } else if (this.time_isYesterday(now, date)) { return this.localizedString("timeFormat.yesterday") + ", " + this.time_formatTime(date); } else if (this.time_isSameYear(now, date)) { return this.time_formatDate(date) + ", " + this.time_formatTime(date); } else { return this.time_formatDateLong(date) + ", " + this.time_formatTime(date); } }; return { getFormattedTime, timeRefreshTrigger, startRefreshTimer, stopRefreshTimer }; });
2. 重构消息组件,动态计算时间文本
不要在组件中缓存格式化后的时间文本,改用computed属性依赖刷新触发标记,确保每次触发时自动重新计算:
<script lang="ts" setup> import { computed } from 'vue'; import { useChatStore } from '@/stores/modules/chat'; const props = defineProps<{ message: { timeFormatted: string; id: number; message: string; }; }>(); const chatStore = useChatStore(); // 依赖刷新触发标记和消息时间,自动重新计算 const currentTimeText = computed(() => { // 读取触发标记,建立响应式依赖 chatStore.timeRefreshTrigger; return chatStore.getFormattedTime(props.message.timeFormatted); }); </script> <template> <span class="text-xs ms-1 text-secondary">{{ currentTimeText }}</span> </template>
原理说明
- 单个定时器:仅在Pinia Store中创建一个定时器,避免为每条消息单独设置定时器造成资源浪费。
- 响应式触发:
timeRefreshTrigger是响应式变量,所有消息组件的computed属性都依赖它,当它的值更新时,所有关联的计算都会自动执行,重新获取最新的时间差文本。 - 性能友好:150条消息的计算量极小,每60秒执行一次完全不会有性能问题,且
computed会缓存结果,只有依赖变化时才重新计算。
内容的提问来源于stack exchange,提问作者Florianb
相关产品推荐
相关产品推荐

