perf(DynamicTracking): 优化组件加载体验,子组件懒加载

- 使用 React.lazy() 懒加载所有子面板组件
- 为每个 Tab 添加专属骨架屏 fallback
- SubTabContainer 同步渲染,点击立即显示二级导航
- 添加 memo、useCallback、useMemo 性能优化
- 新增 DynamicTrackingSkeleton.tsx 骨架屏组件

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
zdl
2025-12-19 17:10:39 +08:00
parent 11544909d3
commit 8c9cc9845d
3 changed files with 170 additions and 17 deletions

View File

@@ -1,37 +1,73 @@
// src/views/Company/components/DynamicTracking/index.js
// 动态跟踪 - 独立一级 Tab 组件(包含新闻动态等二级 Tab
// 优化:子组件懒加载,骨架屏即时反馈
import React, { useState, useEffect, useMemo } from 'react';
import React, { useState, useEffect, useMemo, useCallback, memo, lazy } from 'react';
import { Box } from '@chakra-ui/react';
import { FaNewspaper, FaBullhorn, FaCalendarAlt, FaChartBar } from 'react-icons/fa';
import SubTabContainer from '@components/SubTabContainer';
import AnnouncementsPanel from '../CompanyOverview/BasicInfoTab/components/AnnouncementsPanel';
import DisclosureSchedulePanel from '../CompanyOverview/BasicInfoTab/components/DisclosureSchedulePanel';
import { NewsPanel, ForecastPanel } from './components';
import {
NewsPanelSkeleton,
AnnouncementsSkeleton,
DisclosureScheduleSkeleton,
ForecastPanelSkeleton,
} from './components/DynamicTrackingSkeleton';
// 二级 Tab 配置
// 懒加载子组件
const NewsPanel = lazy(() => import('./components/NewsPanel'));
const ForecastPanel = lazy(() => import('./components/ForecastPanel'));
const AnnouncementsPanel = lazy(() =>
import('../CompanyOverview/BasicInfoTab/components/AnnouncementsPanel')
);
const DisclosureSchedulePanel = lazy(() =>
import('../CompanyOverview/BasicInfoTab/components/DisclosureSchedulePanel')
);
// 二级 Tab 配置(带骨架屏 fallback
const TRACKING_TABS = [
{ key: 'news', name: '新闻动态', icon: FaNewspaper, component: NewsPanel },
{ key: 'announcements', name: '公司公告', icon: FaBullhorn, component: AnnouncementsPanel },
{ key: 'disclosure', name: '财报披露日程', icon: FaCalendarAlt, component: DisclosureSchedulePanel },
{ key: 'forecast', name: '业绩预告', icon: FaChartBar, component: ForecastPanel },
{
key: 'news',
name: '新闻动态',
icon: FaNewspaper,
component: NewsPanel,
fallback: <NewsPanelSkeleton />,
},
{
key: 'announcements',
name: '公司公告',
icon: FaBullhorn,
component: AnnouncementsPanel,
fallback: <AnnouncementsSkeleton />,
},
{
key: 'disclosure',
name: '财报披露日程',
icon: FaCalendarAlt,
component: DisclosureSchedulePanel,
fallback: <DisclosureScheduleSkeleton />,
},
{
key: 'forecast',
name: '业绩预告',
icon: FaChartBar,
component: ForecastPanel,
fallback: <ForecastPanelSkeleton />,
},
];
/**
* 动态跟踪组件
*
* 功能:
* - 使用 SubTabContainer 实现二级导航
* - Tab1: 新闻动态
* - Tab2: 公司公告
* - Tab3: 财报披露日程
* - Tab4: 业绩预告
* - 使用 SubTabContainer 实现二级导航(同步渲染,无 loading
* - 子组件懒加载,减少初始包体积
* - 每个 Tab 有专属骨架屏,提供即时视觉反馈
*
* @param {Object} props
* @param {string} props.stockCode - 股票代码
*/
const DynamicTracking = ({ stockCode: propStockCode }) => {
const DynamicTracking = memo(({ stockCode: propStockCode }) => {
const [stockCode, setStockCode] = useState(propStockCode || '000001');
const [activeTab, setActiveTab] = useState(0);
@@ -50,6 +86,11 @@ const DynamicTracking = ({ stockCode: propStockCode }) => {
[stockCode]
);
// Tab 切换回调
const handleTabChange = useCallback((index) => {
setActiveTab(index);
}, []);
return (
<Box>
<SubTabContainer
@@ -57,12 +98,14 @@ const DynamicTracking = ({ stockCode: propStockCode }) => {
componentProps={componentProps}
themePreset="blackGold"
index={activeTab}
onTabChange={(index) => setActiveTab(index)}
onTabChange={handleTabChange}
isLazy
size="sm"
/>
</Box>
);
};
});
DynamicTracking.displayName = 'DynamicTracking';
export default DynamicTracking;