@@ -29,6 +29,8 @@ interface TreeNodeIProps {
2929interface IContext {
3030 treeData : ITreeNode [ ] ;
3131 setTreeData : ( value : ITreeNode [ ] | null ) => void ;
32+ searchTreeData : ITreeNode [ ] | null ;
33+ setSearchTreeData : ( value : ITreeNode [ ] | null ) => void ;
3234}
3335
3436export const Context = createContext < IContext > ( { } as any ) ;
@@ -48,6 +50,21 @@ const smoothTree = (treeData: ITreeNode[], result: ITreeNode[] = [], parentNode?
4850 return result ;
4951} ;
5052
53+ // 平级转树
54+ function tranListToTreeData ( list :ITreeNode [ ] , rootValue ) {
55+ const arr :ITreeNode [ ] = [ ]
56+ list . forEach ( ( item :ITreeNode ) => {
57+ if ( item . parentNode ?. uuid === rootValue ) {
58+ arr . push ( item )
59+ const children = tranListToTreeData ( list , item . uuid )
60+ if ( children . length ) {
61+ item . children = children
62+ }
63+ }
64+ } )
65+ return arr
66+ }
67+
5168// 判断是否匹配
5269const isMatch = ( target : string , searchValue : string ) => {
5370 const reg = new RegExp ( searchValue , 'i' ) ;
@@ -61,41 +78,29 @@ function searchTree(treeData: ITreeNode[], searchValue: string): ITreeNode[] {
6178 // 深度优先遍历
6279 function dfs ( node : ITreeNode , path : ITreeNode [ ] = [ ] ) {
6380 if ( isMatch ( node . name , searchValue ) ) {
64- // debugger
65- result = [ ...result , ...path , node ] ;
66- // return true;
81+ result = [ ...result , ...path , node ] ;
82+ return ;
6783 }
68- if ( ! node . children ) return false ;
69- for ( const child of node . children ) {
70- // debugger
71- if ( dfs ( child , [ ...path , node ] ) ) {
72- return true ;
73- }
74- }
75- return false ;
84+ if ( ! node . children ) return ;
85+ node . children . forEach ( ( child ) => {
86+ dfs ( child , [ ...path , node ] ) ;
87+ } ) ;
7688 }
7789
7890 // 遍历树
7991 treeData . forEach ( ( node ) => dfs ( node ) ) ;
8092
81- // 如果不匹配,说明该节点为path,不需要保留该节点的子元素,就把children置空
93+ // 根据uuid去重
94+ const deWeightList : ITreeNode [ ] = [ ] ;
8295 result . forEach ( ( item ) => {
83- if ( ! isMatch ( item . name , searchValue ) ) {
96+ // 如果不匹配,说明该节点为path,不需要保留该节点的子元素,就把children置空
97+ if ( ! isMatch ( item . name , searchValue ) ) {
8498 item . children = null ;
8599 }
86- } ) ;
87-
88- // tree转平级
89- const smoothTreeList : ITreeNode [ ] = [ ]
90- smoothTree ( result , smoothTreeList ) ;
91-
92- // 对smoothTreeList根据uuid去重
93- const deWeightList : ITreeNode [ ] = [ ] ;
94- smoothTreeList . forEach ( ( item ) => {
95100 deWeightList . findIndex ( ( i ) => i . uuid === item . uuid ) === - 1 && deWeightList . push ( item ) ;
96101 } ) ;
97102
98- return deWeightList ;
103+ return tranListToTreeData ( deWeightList , undefined ) ;
99104}
100105
101106const itemHeight = 26 ; // 每个 item 的高度
@@ -106,6 +111,8 @@ const Tree = (props: IProps) => {
106111 const [ treeData , setTreeData ] = useState < ITreeNode [ ] | null > ( null ) ;
107112 const [ smoothTreeData , setSmoothTreeData ] = useState < ITreeNode [ ] > ( [ ] ) ;
108113 const [ searchTreeData , setSearchTreeData ] = useState < ITreeNode [ ] | null > ( null ) ; // 搜索结果
114+ const [ searchSmoothTreeData , setSearchSmoothTreeData ] = useState < ITreeNode [ ] | null > ( null ) ; // 搜索结果 平级
115+
109116 const [ scrollTop , setScrollTop ] = useState ( 0 ) ; // 滚动位置 // 继续需要渲染的 item 索引有哪些
110117
111118 const startIdx = useMemo ( ( ) => {
@@ -131,26 +138,45 @@ const Tree = (props: IProps) => {
131138 }
132139 } , [ treeData ] ) ;
133140
141+ // 搜索结果转平级
142+ useEffect ( ( ) => {
143+ if ( searchTreeData ) {
144+ const result : ITreeNode [ ] = [ ] ;
145+ smoothTree ( searchTreeData , result ) ;
146+ setSearchSmoothTreeData ( result ) ;
147+ } else {
148+ setSearchSmoothTreeData ( null ) ;
149+ }
150+ } , [ searchTreeData ] ) ;
151+
134152 const treeNodes = useMemo ( ( ) => {
135- const realNodeList = ( searchTreeData || smoothTreeData ) . slice ( startIdx , startIdx + 50 ) ;
153+ const realNodeList = ( searchSmoothTreeData || smoothTreeData ) . slice ( startIdx , startIdx + 50 ) ;
136154 return realNodeList . map ( ( item ) => {
137- return < TreeNode key = { item . uuid } level = { item . level || 0 } data = { item } /> ;
155+ return < TreeNode key = { item . key } level = { item . level || 0 } data = { item } /> ;
138156 } ) ;
139- } , [ smoothTreeData , searchTreeData , startIdx ] ) ;
157+ } , [ smoothTreeData , searchSmoothTreeData , startIdx ] ) ;
140158
141159 useEffect ( ( ) => {
142160 if ( searchValue && treeData ) {
143- const _searchTreeData = searchTree ( cloneDeep ( treeData ) , searchValue )
161+ const _searchTreeData = searchTree ( cloneDeep ( treeData ) , searchValue ) ;
144162 setSearchTreeData ( _searchTreeData ) ;
145163 setScrollTop ( 0 ) ;
146164 } else {
147165 setSearchTreeData ( null ) ;
148166 }
149- } , [ searchValue , treeData ] ) ;
167+ } , [ searchValue ] ) ;
168+
150169
151170 return (
152171 < LoadingContent isLoading = { ! treeData } className = { classnames ( className ) } >
153- < Context . Provider value = { { treeData : cloneDeep ( treeData ! ) , setTreeData : setTreeData ! } } >
172+ < Context . Provider
173+ value = { {
174+ treeData : treeData ! ,
175+ setTreeData : setTreeData ! ,
176+ searchTreeData,
177+ setSearchTreeData
178+ } }
179+ >
154180 < div
155181 className = { classnames ( styles . scrollBox ) }
156182 onScroll = { ( e : any ) => {
@@ -159,7 +185,7 @@ const Tree = (props: IProps) => {
159185 >
160186 < div
161187 className = { styles . treeListHolder }
162- style = { { '--tree-node-count' : ( searchTreeData || smoothTreeData ) ?. length } as any }
188+ style = { { '--tree-node-count' : ( searchSmoothTreeData || smoothTreeData ) ?. length } as any }
163189 >
164190 < div style = { { height : top } } />
165191 { treeNodes }
@@ -174,15 +200,18 @@ const TreeNode = memo((props: TreeNodeIProps) => {
174200 const { data : treeNodeData , level } = props ;
175201 const [ isLoading , setIsLoading ] = useState ( false ) ;
176202 const indentArr = new Array ( level ) . fill ( 'indent' ) ;
177- const { treeData, setTreeData } = useContext ( Context ) ;
203+ const { treeData, setTreeData, searchTreeData , setSearchTreeData } = useContext ( Context ) ;
178204
179205 // 加载数据
180206 function loadData ( _props ?: { refresh : boolean ; pageNo : number ; treeNodeData ?: ITreeNode } ) {
181207 const _treeNodeData = _props ?. treeNodeData || props . data ;
182208 const treeNodeConfig : ITreeConfigItem = treeConfig [ _treeNodeData . pretendNodeType || _treeNodeData . treeNodeType ] ;
183209 setIsLoading ( true ) ;
184210 if ( _props ?. pageNo === 1 || ! _props ?. pageNo ) {
185- insertData ( treeData ! , _treeNodeData . uuid ! , null ) ;
211+ insertData ( treeData ! , _treeNodeData . uuid ! , null , [ treeData , setTreeData ] ) ;
212+ if ( searchTreeData ) {
213+ insertData ( searchTreeData ! , _treeNodeData . uuid ! , null , [ searchTreeData , setSearchTreeData ] ) ;
214+ }
186215 }
187216
188217 treeNodeConfig
@@ -197,7 +226,10 @@ const TreeNode = memo((props: TreeNodeIProps) => {
197226 . then ( ( res : any ) => {
198227 if ( res . length || res . data ) {
199228 if ( res . data ) {
200- insertData ( treeData ! , _treeNodeData . uuid ! , res . data ) ;
229+ insertData ( treeData ! , _treeNodeData . uuid ! , res . data , [ treeData , setTreeData ] ) ;
230+ if ( searchTreeData ) {
231+ insertData ( searchTreeData ! , _treeNodeData . uuid ! , res . data , [ searchTreeData , setSearchTreeData ] ) ;
232+ }
201233 // TODO:
202234 if ( res . hasNextPage ) {
203235 loadData ( {
@@ -206,7 +238,10 @@ const TreeNode = memo((props: TreeNodeIProps) => {
206238 } ) ;
207239 }
208240 } else {
209- insertData ( treeData ! , _treeNodeData . uuid ! , res ) ;
241+ insertData ( treeData ! , _treeNodeData . uuid ! , res , [ treeData , setTreeData ] ) ;
242+ if ( searchTreeData ) {
243+ insertData ( searchTreeData ! , _treeNodeData . uuid ! , res , [ searchTreeData , setSearchTreeData ] ) ;
244+ }
210245 }
211246 setIsLoading ( false ) ;
212247 } else {
@@ -215,7 +250,10 @@ const TreeNode = memo((props: TreeNodeIProps) => {
215250 _treeNodeData . pretendNodeType = treeNodeConfig . next ;
216251 loadData ( ) ;
217252 } else {
218- insertData ( treeData ! , _treeNodeData . uuid ! , [ ] ) ;
253+ insertData ( treeData ! , _treeNodeData . uuid ! , [ ] , [ treeData , setTreeData ] ) ;
254+ if ( searchTreeData ) {
255+ insertData ( searchTreeData ! , _treeNodeData . uuid ! , [ ] , [ searchTreeData , setSearchTreeData ] ) ;
256+ }
219257 setIsLoading ( false ) ;
220258 }
221259 }
@@ -229,23 +267,28 @@ const TreeNode = memo((props: TreeNodeIProps) => {
229267 const isFocus = useTreeStore ( ( state ) => state . focusId ) === treeNodeData . uuid ;
230268
231269 // 在treeData中找到对应的节点,插入数据
232- const insertData = ( _treeData : ITreeNode [ ] , uuid : string , data : any ) : ITreeNode | null => {
270+ const insertData = ( _treeData : ITreeNode [ ] , uuid : string , data : any , originalDataList :any ) : ITreeNode | null => {
271+ const [ originalData , setOriginalData ] = originalDataList
233272 let result : ITreeNode | null = null ;
234273 for ( let i = 0 ; i < _treeData ?. length ; i ++ ) {
235274 if ( _treeData [ i ] . uuid === uuid ) {
236275 result = _treeData [ i ] ;
237276 if ( data ) {
238- result . children = [ ...( result . children || [ ] ) , ...( data || [ ] ) ] ;
277+ data . map ( ( item : any ) => {
278+ item . parentNode = result ;
279+ } ) ;
280+ // result.children = [...(result.children || []), ...(data || [])];
281+ result . children = [ ...( data || [ ] ) ] ;
239282 } else {
240283 result . children = null ;
241284 }
242- result . expanded = ! ! data ;
285+ // result.expanded = !!data;
243286 // 这里没写错 就是要改变treeData的引用
244- setTreeData ?.( cloneDeep ( treeData || [ ] ) ) ;
287+ setOriginalData ?.( [ ... ( originalData || [ ] ) ] ) ;
245288 break ;
246289 } else {
247290 if ( _treeData [ i ] . children ) {
248- result = insertData ( _treeData [ i ] . children ! , uuid , data ) ;
291+ result = insertData ( _treeData [ i ] . children ! , uuid , data , originalDataList ) ;
249292 if ( result ) {
250293 break ;
251294 }
@@ -257,8 +300,11 @@ const TreeNode = memo((props: TreeNodeIProps) => {
257300
258301 //展开-收起
259302 const handleClick = ( ) => {
260- if ( treeNodeData . expanded ) {
261- insertData ( treeData ! , treeNodeData . uuid ! , null ) ;
303+ if ( treeNodeData ?. children ?. length ) {
304+ insertData ( treeData ! , treeNodeData . uuid ! , null , [ treeData , setTreeData ] ) ;
305+ if ( searchTreeData ) {
306+ insertData ( searchTreeData ! , treeNodeData . uuid ! , null , [ searchTreeData , setSearchTreeData ] ) ;
307+ }
262308 } else {
263309 loadData ( ) ;
264310 }
@@ -372,7 +418,7 @@ const TreeNode = memo((props: TreeNodeIProps) => {
372418 </ Tooltip >
373419 </ Dropdown >
374420 ) ;
375- } , [ isFocus , isLoading , rightClickMenu ] ) ;
421+ } , [ isFocus , isLoading , rightClickMenu , searchTreeData ] ) ;
376422
377423 return treeNodeDom ;
378424} ) ;
0 commit comments