refactor: 前端性能优化 — 倒计时组件隔离、React memoization 链路
- 新建 RefreshCountdown 组件,内部持有 timer,消除 App 每秒重渲染 - TargetBoard 分组逻辑 useMemo 化,避免 targets 引用不变时重复计算 - TargetGroup 加 React.memo,阻断无效渲染 - TrendChart 加 React.memo + chartData useMemo,避免 recharts 不必要重绘 - OverviewTab 统计项去掉 Card 包裹,改用纯 CSS 实现视觉效果 - 同步更新 refresh-control 和 target-detail-drawer spec 性能提升:消除每秒全组件树重渲染,减少 DOM 节点数
This commit is contained in:
52
src/web/components/RefreshCountdown.tsx
Normal file
52
src/web/components/RefreshCountdown.tsx
Normal file
@@ -0,0 +1,52 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { RefreshIcon } from "tdesign-icons-react";
|
||||
import { Button, Typography } from "tdesign-react";
|
||||
|
||||
import { formatCountdown } from "../utils/time";
|
||||
|
||||
interface RefreshCountdownProps {
|
||||
dashboardUpdatedAt: number;
|
||||
isFetching: boolean;
|
||||
isManualRefresh: boolean;
|
||||
onRefresh: () => void;
|
||||
refreshInterval: number;
|
||||
}
|
||||
|
||||
export function RefreshCountdown({
|
||||
dashboardUpdatedAt,
|
||||
isFetching,
|
||||
isManualRefresh,
|
||||
onRefresh,
|
||||
refreshInterval,
|
||||
}: RefreshCountdownProps) {
|
||||
const [now, setNow] = useState(() => new Date());
|
||||
|
||||
useEffect(() => {
|
||||
const timer = window.setInterval(() => setNow(new Date()), 1000);
|
||||
return () => window.clearInterval(timer);
|
||||
}, []);
|
||||
|
||||
const nextRefreshSeconds =
|
||||
dashboardUpdatedAt > 0 && !isManualRefresh
|
||||
? Math.max(0, Math.ceil((dashboardUpdatedAt + refreshInterval - now.getTime()) / 1000))
|
||||
: null;
|
||||
|
||||
if (isManualRefresh) {
|
||||
return (
|
||||
<Button
|
||||
aria-label="刷新 Dashboard"
|
||||
disabled={isFetching}
|
||||
icon={<RefreshIcon />}
|
||||
loading={isFetching}
|
||||
onClick={() => void onRefresh()}
|
||||
shape="circle"
|
||||
variant="outline"
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
const refreshText =
|
||||
dashboardUpdatedAt > 0 ? (isFetching ? "刷新中..." : formatCountdown(nextRefreshSeconds ?? 0)) : "等待首次刷新";
|
||||
|
||||
return <Typography.Text theme="secondary">{refreshText}</Typography.Text>;
|
||||
}
|
||||
Reference in New Issue
Block a user