11import type React from 'react' ;
2- import { useCallback , useEffect , useRef } from 'react' ;
2+ import { useCallback , useEffect , useRef , useState } from 'react' ;
33import { cssPrefix } from '../../configs' ;
4- import { useActiveSheet } from '../../store/useSheetStore' ;
4+ import { useActiveSheet , useSheetStore } from '../../store/useSheetStore' ;
55
66interface ScrollbarProps {
77 vertical ?: boolean ;
@@ -16,50 +16,67 @@ export const Scrollbar: React.FC<ScrollbarProps> = ({
1616 const scrollRef = useRef < HTMLDivElement > ( null ) ;
1717 const contentRef = useRef < HTMLDivElement > ( null ) ;
1818 const isScrollingRef = useRef ( false ) ;
19+ const [ dimensions , setDimensions ] = useState ( {
20+ scrollbarSize : 0 ,
21+ contentSize : 0 ,
22+ visible : false ,
23+ } ) ;
1924
20- // 设置滚动条尺寸和位置
25+ // 计算滚动条尺寸
2126 useEffect ( ( ) => {
22- if ( ! data || ! scrollRef . current || ! contentRef . current ) return ;
23-
24- const { rows, cols, scroll } = data ;
25- const viewWidth = data . viewWidth ( ) ;
26- const viewHeight = data . viewHeight ( ) ;
27-
28- if ( vertical ) {
29- const height = viewHeight - 1 ;
30- const exceptRowTotalHeight = data . exceptRowTotalHeight ( 0 , - 1 ) ;
31- const contentDistance = rows . totalHeight ( ) - exceptRowTotalHeight ;
32-
33- if ( contentDistance > height ) {
34- scrollRef . current . style . height = `${ height - 15 } px` ;
35- scrollRef . current . style . display = 'block' ;
36- contentRef . current . style . width = '1px' ;
37- contentRef . current . style . height = `${ contentDistance } px` ;
38- // 同步滚动位置
39- if ( ! isScrollingRef . current ) {
40- scrollRef . current . scrollTop = scroll . y ;
41- }
27+ if ( ! data ) return ;
28+
29+ const updateDimensions = ( ) => {
30+ const { rows, cols } = data ;
31+ const viewWidth = data . viewWidth ( ) ;
32+ const viewHeight = data . viewHeight ( ) ;
33+
34+ if ( vertical ) {
35+ const height = viewHeight - 1 ;
36+ const exceptRowTotalHeight = data . exceptRowTotalHeight ( 0 , - 1 ) ;
37+ const contentDistance = rows . totalHeight ( ) - exceptRowTotalHeight ;
38+
39+ setDimensions ( {
40+ scrollbarSize : height - 15 ,
41+ contentSize : contentDistance ,
42+ visible : contentDistance > height ,
43+ } ) ;
4244 } else {
43- scrollRef . current . style . display = 'none' ;
45+ const width = viewWidth - 1 ;
46+ const contentDistance = cols . totalWidth ( ) ;
47+
48+ setDimensions ( {
49+ scrollbarSize : width - 15 ,
50+ contentSize : contentDistance ,
51+ visible : contentDistance > width ,
52+ } ) ;
4453 }
45- } else {
46- const width = viewWidth - 1 ;
47- const contentDistance = cols . totalWidth ( ) ;
48-
49- if ( contentDistance > width ) {
50- scrollRef . current . style . width = `${ width - 15 } px` ;
51- scrollRef . current . style . display = 'block' ;
52- contentRef . current . style . height = '1px' ;
53- contentRef . current . style . width = `${ contentDistance } px` ;
54- // 同步滚动位置
55- if ( ! isScrollingRef . current ) {
56- scrollRef . current . scrollLeft = scroll . x ;
57- }
54+ } ;
55+
56+ // 初始计算
57+ updateDimensions ( ) ;
58+
59+ // 订阅 store 变化
60+ const unsubscribe = useSheetStore . subscribe ( ( ) => {
61+ updateDimensions ( ) ;
62+ } ) ;
63+
64+ return unsubscribe ;
65+ } , [ data , vertical ] ) ;
66+
67+ // 同步滚动位置
68+ useEffect ( ( ) => {
69+ if ( ! data || ! scrollRef . current || ! dimensions . visible ) return ;
70+
71+ const { scroll } = data ;
72+ if ( ! isScrollingRef . current ) {
73+ if ( vertical ) {
74+ scrollRef . current . scrollTop = scroll . y ;
5875 } else {
59- scrollRef . current . style . display = 'none' ;
76+ scrollRef . current . scrollLeft = scroll . x ;
6077 }
6178 }
62- } , [ data , vertical ] ) ;
79+ } , [ data , vertical , dimensions . visible ] ) ;
6380
6481 const handleScroll = useCallback (
6582 ( e : React . UIEvent < HTMLDivElement > ) => {
@@ -78,7 +95,7 @@ export const Scrollbar: React.FC<ScrollbarProps> = ({
7895 [ vertical , onScroll ] ,
7996 ) ;
8097
81- if ( ! data ) return null ;
98+ if ( ! data || ! dimensions . visible ) return null ;
8299
83100 return (
84101 < div
@@ -94,9 +111,20 @@ export const Scrollbar: React.FC<ScrollbarProps> = ({
94111 zIndex : 12 ,
95112 overflowX : vertical ? 'hidden' : 'scroll' ,
96113 overflowY : vertical ? 'scroll' : 'hidden' ,
114+ ...( vertical
115+ ? { height : dimensions . scrollbarSize }
116+ : { width : dimensions . scrollbarSize } ) ,
97117 } }
98118 >
99- < div ref = { contentRef } style = { { background : '#ddd' } } />
119+ < div
120+ ref = { contentRef }
121+ style = { {
122+ background : '#ddd' ,
123+ ...( vertical
124+ ? { width : 1 , height : dimensions . contentSize }
125+ : { height : 1 , width : dimensions . contentSize } ) ,
126+ } }
127+ />
100128 </ div >
101129 ) ;
102130} ;
0 commit comments