diff --git a/src/components/SubTabContainer/index.tsx b/src/components/SubTabContainer/index.tsx index 668f835a..971516c1 100644 --- a/src/components/SubTabContainer/index.tsx +++ b/src/components/SubTabContainer/index.tsx @@ -181,6 +181,11 @@ const SubTabContainer: React.FC = memo(({ () => new Set([controlledIndex ?? defaultIndex]) ); + // 记录每个 Tab 的激活次数(用于支持特定 Tab 切换时重新请求) + const [activationCounts, setActivationCounts] = useState>( + () => ({ [controlledIndex ?? defaultIndex]: 1 }) + ); + // 合并主题 const theme: SubTabTheme = { ...THEME_PRESETS[themePreset], @@ -192,6 +197,9 @@ const SubTabContainer: React.FC = memo(({ */ const handleTabChange = useCallback( (newIndex: number) => { + // 保存当前滚动位置,防止 Tab 切换时页面跳转 + const scrollY = window.scrollY; + const tabKey = tabs[newIndex]?.key || ''; onTabChange?.(newIndex, tabKey); @@ -201,9 +209,20 @@ const SubTabContainer: React.FC = memo(({ return new Set(prev).add(newIndex); }); + // 更新激活计数(用于触发特定 Tab 的数据刷新) + setActivationCounts(prev => ({ + ...prev, + [newIndex]: (prev[newIndex] || 0) + 1, + })); + if (controlledIndex === undefined) { setInternalIndex(newIndex); } + + // 恢复滚动位置,阻止浏览器自动滚动 + requestAnimationFrame(() => { + window.scrollTo(0, scrollY); + }); }, [tabs, onTabChange, controlledIndex] ); @@ -343,6 +362,8 @@ const SubTabContainer: React.FC = memo(({ const Component = tab.component; // 懒加载:只渲染已访问过的 Tab const shouldRender = !isLazy || visitedTabs.has(idx); + // 判断是否为当前激活的 Tab(用于控制数据加载) + const isActive = idx === currentIndex; return ( @@ -361,7 +382,11 @@ const SubTabContainer: React.FC = memo(({ ) } > - + ) : null} diff --git a/src/components/TabPanelContainer/index.tsx b/src/components/TabPanelContainer/index.tsx index f45c3e9e..95b25c51 100644 --- a/src/components/TabPanelContainer/index.tsx +++ b/src/components/TabPanelContainer/index.tsx @@ -28,6 +28,8 @@ export interface TabPanelContainerProps { loadingMessage?: string; /** 加载状态高度 */ loadingHeight?: string; + /** 自定义骨架屏组件,优先于默认 Spinner */ + skeleton?: React.ReactNode; /** 子组件间距,默认 6 */ spacing?: number; /** 内边距,默认 4 */ @@ -74,6 +76,7 @@ const TabPanelContainer: React.FC = memo( loading = false, loadingMessage = '加载中...', loadingHeight = '200px', + skeleton, spacing = 6, padding = 4, showDisclaimer = false, @@ -81,6 +84,10 @@ const TabPanelContainer: React.FC = memo( children, }) => { if (loading) { + // 如果提供了自定义骨架屏,使用骨架屏;否则使用默认 Spinner + if (skeleton) { + return <>{skeleton}; + } return ; }