feat: 添加 React 性能追踪 Hooks (usePerformanceTracker)
- usePerformanceTracker: 自动追踪组件渲染性能(mount/rendered/unmount) - usePerformanceMark: 手动标记自定义操作的性能 - 基于 performanceMonitor.ts 封装,提供 React 友好的 API - 完整 TypeScript 类型支持 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
129
src/hooks/usePerformanceTracker.ts
Normal file
129
src/hooks/usePerformanceTracker.ts
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
/**
|
||||||
|
* React 性能追踪 Hooks
|
||||||
|
* 封装 performanceMonitor 工具,提供 React 友好的性能追踪 API
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { useEffect, useRef, useCallback } from 'react';
|
||||||
|
import { performanceMonitor } from '@utils/performanceMonitor';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* usePerformanceMark 返回值类型
|
||||||
|
*/
|
||||||
|
export interface UsePerformanceMarkReturn {
|
||||||
|
/** 标记时间点 */
|
||||||
|
mark: (suffix: string) => void;
|
||||||
|
/** 测量并记录到 performanceMonitor */
|
||||||
|
measure: (startSuffix: string, endSuffix: string, name?: string) => number | null;
|
||||||
|
/** 获取测量值(不记录) */
|
||||||
|
getMeasure: (startSuffix: string, endSuffix: string) => number | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* usePerformanceTracker - 自动追踪组件渲染性能
|
||||||
|
*
|
||||||
|
* @param componentName - 组件名称,用于标记
|
||||||
|
* @param options - 配置选项
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* ```tsx
|
||||||
|
* function MyComponent() {
|
||||||
|
* usePerformanceTracker('MyComponent');
|
||||||
|
* return <div>...</div>;
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* 自动标记:
|
||||||
|
* - {componentName}-mount: 组件挂载时
|
||||||
|
* - {componentName}-rendered: 首次渲染完成
|
||||||
|
* - {componentName}-unmount: 组件卸载时
|
||||||
|
*/
|
||||||
|
export function usePerformanceTracker(
|
||||||
|
componentName: string,
|
||||||
|
options: { trackRender?: boolean } = {}
|
||||||
|
): void {
|
||||||
|
const { trackRender = true } = options;
|
||||||
|
const hasMounted = useRef(false);
|
||||||
|
|
||||||
|
// 首次渲染时立即标记(同步)
|
||||||
|
if (!hasMounted.current) {
|
||||||
|
performanceMonitor.mark(`${componentName}-mount`);
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!hasMounted.current) {
|
||||||
|
hasMounted.current = true;
|
||||||
|
|
||||||
|
// 渲染完成标记(在 useEffect 中,表示 DOM 已更新)
|
||||||
|
if (trackRender) {
|
||||||
|
performanceMonitor.mark(`${componentName}-rendered`);
|
||||||
|
performanceMonitor.measure(
|
||||||
|
`${componentName}-mount`,
|
||||||
|
`${componentName}-rendered`,
|
||||||
|
`${componentName} 渲染`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 组件卸载时标记
|
||||||
|
return () => {
|
||||||
|
performanceMonitor.mark(`${componentName}-unmount`);
|
||||||
|
};
|
||||||
|
}, [componentName, trackRender]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* usePerformanceMark - 手动标记自定义操作的性能
|
||||||
|
*
|
||||||
|
* @param prefix - 标记前缀,用于区分不同操作
|
||||||
|
* @returns 包含 mark、measure、getMeasure 方法的对象
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* ```tsx
|
||||||
|
* function MyComponent() {
|
||||||
|
* const { mark, getMeasure } = usePerformanceMark('api-call');
|
||||||
|
*
|
||||||
|
* const handleFetch = async () => {
|
||||||
|
* mark('start');
|
||||||
|
* await fetchData();
|
||||||
|
* mark('end');
|
||||||
|
* const duration = getMeasure('start', 'end');
|
||||||
|
* console.log('API耗时:', duration, 'ms');
|
||||||
|
* };
|
||||||
|
*
|
||||||
|
* return <button onClick={handleFetch}>加载数据</button>;
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
export function usePerformanceMark(prefix: string): UsePerformanceMarkReturn {
|
||||||
|
const mark = useCallback(
|
||||||
|
(suffix: string) => {
|
||||||
|
performanceMonitor.mark(`${prefix}-${suffix}`);
|
||||||
|
},
|
||||||
|
[prefix]
|
||||||
|
);
|
||||||
|
|
||||||
|
const measure = useCallback(
|
||||||
|
(startSuffix: string, endSuffix: string, name?: string) => {
|
||||||
|
return performanceMonitor.measure(
|
||||||
|
`${prefix}-${startSuffix}`,
|
||||||
|
`${prefix}-${endSuffix}`,
|
||||||
|
name || `${prefix}: ${startSuffix} → ${endSuffix}`
|
||||||
|
);
|
||||||
|
},
|
||||||
|
[prefix]
|
||||||
|
);
|
||||||
|
|
||||||
|
const getMeasure = useCallback(
|
||||||
|
(startSuffix: string, endSuffix: string) => {
|
||||||
|
return performanceMonitor.measure(
|
||||||
|
`${prefix}-${startSuffix}`,
|
||||||
|
`${prefix}-${endSuffix}`
|
||||||
|
);
|
||||||
|
},
|
||||||
|
[prefix]
|
||||||
|
);
|
||||||
|
|
||||||
|
return { mark, measure, getMeasure };
|
||||||
|
}
|
||||||
|
|
||||||
|
export default usePerformanceTracker;
|
||||||
Reference in New Issue
Block a user