Skip to content

Commit 1828932

Browse files
sealdayclaude
andcommitted
fix: scrollbar visibility using React state instead of DOM manipulation
- Use useState for dimensions instead of direct DOM manipulation - Subscribe to store changes to update scrollbar dimensions - Render scrollbar based on visibility state 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent c27c883 commit 1828932

1 file changed

Lines changed: 69 additions & 41 deletions

File tree

Lines changed: 69 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import type React from 'react';
2-
import { useCallback, useEffect, useRef } from 'react';
2+
import { useCallback, useEffect, useRef, useState } from 'react';
33
import { cssPrefix } from '../../configs';
4-
import { useActiveSheet } from '../../store/useSheetStore';
4+
import { useActiveSheet, useSheetStore } from '../../store/useSheetStore';
55

66
interface 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

Comments
 (0)