1- import React , { useState } from 'react'
1+ import React , { useState , useMemo } from 'react'
22import styles from './index.module.less'
33
4- // 模拟组件数据
5- const mockComponents = {
6- '0' : ( ) => < div className = { styles . mockContent } > 首页内容</ div > ,
7- '1' : ( ) => < div className = { styles . mockContent } > 产品介绍内容</ div > ,
8- '2' : ( ) => < div className = { styles . mockContent } > 关于我们内容</ div > ,
9- '3-0' : ( ) => < div className = { styles . mockContent } > 服务概览内容</ div > ,
10- '3-1' : ( ) => < div className = { styles . mockContent } > 技术支持内容</ div > ,
11- '3-2' : ( ) => < div className = { styles . mockContent } > 售后服务内容</ div > ,
12- '4' : ( ) => < div className = { styles . mockContent } > 联系我们内容</ div > ,
4+ export interface TabItem {
5+ label : string
6+ key ?: string | number
7+ content ?: React . ReactNode
8+ children ?: TabItem [ ]
139}
1410
15- const NavigationTabs : React . FC = ( ) => {
16- const [ activeIndex , setActiveIndex ] = useState < number > ( 0 )
17- const [ subActiveIndex , setSubActiveIndex ] = useState < string > ( '' )
11+ export interface NavigationTabsProps {
12+ items ?: TabItem [ ]
13+ className ?: string
14+ style ?: React . CSSProperties
15+ }
1816
19- // 导航数据
20- const navItems = [
21- { label : '首页' } ,
22- { label : '产品' } ,
23- { label : '关于' } ,
24- {
25- label : '服务' ,
26- children : [ { label : '概览' } , { label : '技术支持' } , { label : '售后' } ] ,
27- } ,
28- { label : '联系' } ,
29- ]
17+ // 默认模拟数据,用于演示组件功能
18+ const defaultItems : TabItem [ ] = [
19+ {
20+ label : '首页' ,
21+ content : < div className = { styles . mockContent } > 首页内容</ div > ,
22+ } ,
23+ {
24+ label : '产品' ,
25+ content : < div className = { styles . mockContent } > 产品介绍内容</ div > ,
26+ } ,
27+ {
28+ label : '关于' ,
29+ content : < div className = { styles . mockContent } > 关于我们内容</ div > ,
30+ } ,
31+ {
32+ label : '服务' ,
33+ children : [
34+ { label : '概览' , content : < div className = { styles . mockContent } > 服务概览内容</ div > } ,
35+ { label : '技术支持' , content : < div className = { styles . mockContent } > 技术支持内容</ div > } ,
36+ { label : '售后' , content : < div className = { styles . mockContent } > 售后服务内容</ div > } ,
37+ ] ,
38+ } ,
39+ {
40+ label : '联系' ,
41+ content : < div className = { styles . mockContent } > 联系我们内容</ div > ,
42+ } ,
43+ ]
44+
45+ const NavigationTabs : React . FC < NavigationTabsProps > = ( { items = defaultItems , className, style } ) => {
46+ const [ activeIndex , setActiveIndex ] = useState < number > ( 0 )
47+ const [ subActiveIndex , setSubActiveIndex ] = useState < number > ( 0 )
3048
31- // 处理一级导航点击
3249 const handleTabClick = ( index : number ) => {
3350 setActiveIndex ( index )
34- const item = navItems [ index ]
35-
36- // 如果有子项,默认选中第一个子项
37- if ( item . children && item . children . length > 0 ) {
38- setSubActiveIndex ( `${ index } -0` )
39- } else {
40- setSubActiveIndex ( '' )
41- }
51+ setSubActiveIndex ( 0 ) // 切换一级导航时,重置二级导航选中项
4252 }
4353
44- // 处理二级导航点击
45- const handleSubTabClick = ( parentIndex : number , subIndex : number ) => {
46- setSubActiveIndex ( `${ parentIndex } -${ subIndex } ` )
54+ const handleSubTabClick = ( index : number ) => {
55+ setSubActiveIndex ( index )
4756 }
4857
49- // 获取当前要渲染的组件
50- const getCurrentComponent = ( ) => {
51- const key = subActiveIndex || activeIndex . toString ( )
52- const Component = mockComponents [ key as keyof typeof mockComponents ]
53- return Component ? < Component /> : < div className = { styles . mockContent } > 默认内容</ div >
54- }
58+ const activeItem = items [ activeIndex ]
59+ const subItems = activeItem ?. children || [ ]
60+ const hasChildren = subItems . length > 0
61+
62+ // 获取当前显示的内容
63+ const currentContent = useMemo ( ( ) => {
64+ if ( hasChildren ) {
65+ return subItems [ subActiveIndex ] ?. content || null
66+ }
67+ return activeItem ?. content || null
68+ } , [ activeItem , hasChildren , subItems , subActiveIndex ] )
5569
5670 return (
57- < div className = { styles . container } >
71+ < div className = { ` ${ styles . container } ${ className || '' } ` } style = { style } >
5872 { /* 一级导航 */ }
5973 < div className = { styles . tabsContainer } >
6074 < div className = { styles . tabsList } >
61- { navItems . map ( ( item , index ) => {
75+ { items . map ( ( item , index ) => {
6276 const isActive = activeIndex === index
63- const hasChildren = item . children && item . children . length > 0
64- const isActiveWithChildren = isActive && hasChildren
77+ const itemHasChildren = item . children && item . children . length > 0
6578
6679 return (
6780 < div
6881 key = { index }
6982 className = { `${ styles . tabItem } ${
70- isActiveWithChildren ? styles . hasArrow : isActive ? styles . actived : ''
83+ itemHasChildren && isActive ? styles . hasArrow : isActive ? styles . actived : ''
7184 } `}
7285 onClick = { ( ) => handleTabClick ( index ) }
7386 >
7487 < span > { item . label } </ span >
75- { hasChildren && < span className = { `${ styles . arrow } ${ isActive ? styles . arrowDown : '' } ` } > ▼</ span > }
88+ { itemHasChildren && < span className = { `${ styles . arrow } ${ isActive ? styles . arrowDown : '' } ` } > ▼</ span > }
7689 </ div >
7790 )
7891 } ) }
7992 </ div >
8093
8194 { /* 二级导航 */ }
82- { navItems [ activeIndex ] ?. children && (
95+ { hasChildren && (
8396 < div className = { styles . subTabsList } >
84- { navItems [ activeIndex ] . children ! . map ( ( subItem , subIndex ) => {
85- const isSubActive = subActiveIndex === `${ activeIndex } -${ subIndex } `
86-
97+ { subItems . map ( ( subItem , index ) => {
98+ const isSubActive = subActiveIndex === index
8799 return (
88100 < div
89- key = { subIndex }
101+ key = { index }
90102 className = { `${ styles . subTabItem } ${ isSubActive ? styles . presented : '' } ` }
91- onClick = { ( ) => handleSubTabClick ( activeIndex , subIndex ) }
103+ onClick = { ( e ) => {
104+ e . stopPropagation ( )
105+ handleSubTabClick ( index )
106+ } }
92107 >
93108 { subItem . label }
94109 </ div >
@@ -99,7 +114,7 @@ const NavigationTabs: React.FC = () => {
99114 </ div >
100115
101116 { /* 内容区域 */ }
102- < div className = { styles . contentArea } > { getCurrentComponent ( ) } </ div >
117+ < div className = { styles . contentArea } > { currentContent || < div className = { styles . mockContent } > 暂无内容 </ div > } </ div >
103118 </ div >
104119 )
105120}
0 commit comments