@@ -11,7 +11,18 @@ export interface OverflowListAdapter extends DefaultAdapter {
1111 getItemSizeMap : ( ) => Map < string , number >
1212}
1313
14+ // 防抖稳定性检测的时间阈值(毫秒)
15+ const STABILITY_THRESHOLD_MS = 150 ;
16+
1417class OverflowListFoundation extends BaseFoundation < OverflowListAdapter > {
18+ // 记录上次的 overflow 结果,用于稳定性检测
19+ previousOverflowResult : Array < Array < Record < string , any > > > = [ [ ] , [ ] ] ;
20+
21+ // 记录每个 item 的状态变化历史(时间戳)
22+ stateChangeHistory : Map < string , number [ ] > = new Map ( ) ;
23+
24+ // 最后一次稳定更新的时间戳
25+ lastStableUpdateTimestamp : number = 0 ;
1526
1627 constructor ( adapter : OverflowListAdapter ) {
1728 super ( { ...adapter } ) ;
@@ -35,11 +46,51 @@ class OverflowListFoundation extends BaseFoundation<OverflowListAdapter> {
3546 const visibleStart = visibleStateArr . indexOf ( true ) ;
3647 const visibleEnd = visibleStateArr . lastIndexOf ( true ) ;
3748
38- const overflowList = [ ] ;
49+ const overflowList : Array < Array < Record < string , any > > > = [ ] ;
3950 overflowList [ 0 ] = visibleStart >= 0 ? items . slice ( 0 , visibleStart ) : [ ] ;
4051 overflowList [ 1 ] = visibleEnd >= 0 ? items . slice ( visibleEnd + 1 , items . length ) : items ;
52+
53+ // 稳定性检测:比较新旧 overflow 结果
54+ const isResultChanged = this . isOverflowResultChanged ( overflowList ) ;
55+
56+ if ( isResultChanged ) {
57+ const now = Date . now ( ) ;
58+ const timeSinceLastUpdate = now - this . lastStableUpdateTimestamp ;
59+
60+ // 如果距离上次稳定更新时间太短,说明可能在抖动,返回上次稳定结果
61+ if ( timeSinceLastUpdate < STABILITY_THRESHOLD_MS && this . previousOverflowResult [ 0 ] . length + this . previousOverflowResult [ 1 ] . length > 0 ) {
62+ return this . previousOverflowResult ;
63+ }
64+
65+ // 更新稳定状态
66+ this . lastStableUpdateTimestamp = now ;
67+ this . previousOverflowResult = overflowList ;
68+ }
69+
4170 return overflowList ;
4271 }
72+
73+ /**
74+ * 检查 overflow 结果是否发生变化
75+ */
76+ isOverflowResultChanged ( newResult : Array < Array < Record < string , any > > > ) : boolean {
77+ const prevLeft = this . previousOverflowResult [ 0 ] ;
78+ const prevRight = this . previousOverflowResult [ 1 ] ;
79+ const newLeft = newResult [ 0 ] ;
80+ const newRight = newResult [ 1 ] ;
81+
82+ if ( prevLeft . length !== newLeft . length || prevRight . length !== newRight . length ) {
83+ return true ;
84+ }
85+
86+ // 比较 key 是否一致
87+ const prevLeftKeys = prevLeft . map ( item => item . key ) . join ( ',' ) ;
88+ const prevRightKeys = prevRight . map ( item => item . key ) . join ( ',' ) ;
89+ const newLeftKeys = newLeft . map ( item => item . key ) . join ( ',' ) ;
90+ const newRightKeys = newRight . map ( item => item . key ) . join ( ',' ) ;
91+
92+ return prevLeftKeys !== newLeftKeys || prevRightKeys !== newRightKeys ;
93+ }
4394
4495 handleIntersect ( entries : Array < IntersectionObserverEntry > ) : void {
4596 const visibleState = cloneDeep ( this . getState ( 'visibleState' ) ) ;
0 commit comments